類擴展(Class Extension)
- 作用
- 能為某個類增加額外的屬性、成員變量、方法聲明
- 一般將類擴展寫到.m文件中
一般將一些私有的屬性寫到類擴展
- 使用格式
@interface 類名()
/* 屬性、成員變量、方法聲明 */
@end
- 與分類的區別
- 分類的小括號必須有名字
@interface 類名(分類名字)
/* 方法聲明 */
@end
@implementation 類名(分類名字)
/* 方法實現 */
@end
- 分類只能擴充方法
- 如果在分類中聲明了一個屬性,分類只會生成這個屬性的get\set方法聲明,`并不會生成成員變量`
項目的常見屬性
- Product Name
- 產品名稱
- 項目名稱
- 軟件名稱
- Organization Name
- 公司名稱
- Organization Identifier
- 公司的唯一標識
- 一般用網站域名的反寫形式
- Bundle Identifier
- 軟件的唯一標識
- 默認 == Organization Identifier + Product Name
九宮格的計算方式
/************** 一些常用的變量 begin **************/
// 每一行的列數
NSUInteger colsPerRow = 3;
// 獲得當前商品的索引
NSUInteger index = self.shopsView.subviews.count;
// 商品寬度
CGFloat shopW = 70;
// 商品高度
CGFloat shopH = 90;
/************** 一些常用的變量 end **************/
/************** 計算X值 begin **************/
// 求出列號
NSUInteger col = index % colsPerRow;
// 每一列之間的間距
CGFloat xMargin = (self.shopsView.frame.size.width - colsPerRow * shopW) / (colsPerRow - 1);
// 商品X
CGFloat shopX = (shopW + xMargin) * col;
/************** 計算X值 end **************/
/************** 計算Y值 begin **************/
// 求出行號
NSUInteger row = index / colsPerRow;
// 每一行之間的間距
CGFloat yMargin = 20;
// 商品Y
CGFloat shopY = (shopH + yMargin) * row;
/************** 計算X值 end **************/
UIImageView
// 內容模式:一般用來控制圖片如何顯示
imageView.contentMode = UIViewContentModeScaleAspectFit;
// 裁剪超出imageView邊框的部分
imageView.clipsToBounds = YES;
// 設置動畫圖片
self.imageView.animationImages;
// 設置播放次數
self.imageView.animationRepeatCount
// 設置動畫的時間
self.imageView.animationDuration
// 開始動畫
[self.imageView startAnimating];
contentMode屬性
-
帶有scale單詞的:圖片有可能會拉伸
- UIViewContentModeScaleToFill
- 將圖片拉伸至填充整個imageView
- 圖片顯示的尺寸跟imageView的尺寸是一樣的
- 帶有aspect單詞的:保持圖片原來的寬高比
- UIViewContentModeScaleAspectFit
- 保證剛好能看到圖片的全部
- UIViewContentModeScaleAspectFill
- 拉伸至圖片的寬度或者高度跟imageView一樣
- UIViewContentModeScaleToFill
-
沒有scale單詞的:圖片絕對不會被拉伸,保持圖片的原尺寸
- UIViewContentModeCenter
- UIViewContentModeTop
- UIViewContentModeBottom
- UIViewContentModeLeft
- UIViewContentModeRight
- UIViewContentModeTopLeft
- UIViewContentModeTopRight
- UIViewContentModeBottomLeft
- UIViewContentModeBottomRight
小語法點
- 不能直接修改:OC對象的結構體屬性的成員
- 下面的寫法是錯誤的
imageView.frame.size = imageView.image.size;
- 正確寫法
CGRect tempFrame = imageView.frame;
tempFrame.size = imageView.image.size;
imageView.frame = tempFrame;
initWithImage:方法
- 利用這個方法創建出來的imageView的尺寸和傳入的圖片尺寸一樣
修改frame的3種方式
- 直接使用CGRectMake函數
imageView.frame = CGRectMake(100, 100, 200, 200);
- 利用臨時結構體變量
CGRect tempFrame = imageView.frame;
tempFrame.origin.x = 100;
tempFrame.origin.y = 100;
tempFrame.size.width = 200;
tempFrame.size.height = 200;
imageView.frame = tempFrame;
- 使用大括號{}形式
imageView.frame = (CGRect){{100, 100}, {200, 200}};
- 圖片的加載方式
- 1、有緩存
UIImage *image = [UIImage imageNamed:@"圖片名"];
//使用場合:圖片比較小、使用頻率較高
//建議把需要緩存的圖片直接放到Images.xcassets
- 2、無緩存
NSString *file = [[NSBundle mainBundle] pathForResource:@"圖片名" ofType:@"圖片的擴展名"];
UIImage *image = [UIImage imageWithContentsOfFile:@"圖片文件的全路徑"];
//使用場合:圖片比較大、使用頻率較小
//不需要緩存的圖片不能放在Images.xcassets
//放在Images.xcassets里面的圖片,只能通過圖片名去加載圖片
UIControl
- 凡是繼承自UIControl的控件,都可以通過addTarget:...方法來監聽事件
UILabel
- 內容包含模式
UILabel *la = [[UILabel alloc] init];
la.lineBreakMode = NSLineBreakByWordWrapping;//保持單詞的完整性
@property的使用策略
- assign
-
基本數據類型
、枚舉
、結構體
等非OC對象類型
-
- weak
- OC對象類型(比如NSArray、NSDate、NSNumber、模型類)
- strong
- OC對象類型(比如NSArray、NSDate、NSNumber、模型類)
- 一個對象只要有強指針引用著,就不會被銷毀
- copy
- 一般用在
NSString
、block
類型上
- 一般用在
自定義控件的步驟
1、通過純代碼自定義控件
- 繼承自系統自帶的控件,寫一個屬于自己的控件
- 目的:封裝控件內部的細節,不讓外界關心
- 步驟
- 新建一個繼承
UIView
的類 - 在
initWithFrame:
方法中添加子控件 - 在
layoutSubviews
方法中設置子控件的frame- 一定要調用
[super layoutSubviews]
;
- 一定要調用
- 提供一個模型屬性,重寫模型屬性的set方法
- 在set方法中取出模型屬性,給對應的子控件賦值
- 新建一個繼承
2、通過xib自定義控件
- 新建一個繼承
UIView
的類 - 新建一個xib文件(xib的文件名最好跟控件類名一樣)
- 添加子控件、設置子控件屬性
- 修改最外面那個控件的class為控件類名
- 將子控件進行連線
- 提供模型屬性,重寫模型的set方法
- 在set方法中給子控件設置數據
中間的提醒內容
- 指示器、HUD、遮蓋、蒙板
- 半透明的指示器如何實現?
- 指示器的alpha = 1.0
- 指示器的背景色是半透明的
創建顏色
- 直接創建對應的顏色
+ (UIColor *)blackColor; // 0.0 white
+ (UIColor *)darkGrayColor; // 0.333 white
+ (UIColor *)lightGrayColor; // 0.667 white
+ (UIColor *)whiteColor; // 1.0 white
+ (UIColor *)grayColor; // 0.5 white
+ (UIColor *)redColor; // 1.0, 0.0, 0.0 RGB
+ (UIColor *)greenColor; // 0.0, 1.0, 0.0 RGB
+ (UIColor *)blueColor; // 0.0, 0.0, 1.0 RGB
+ (UIColor *)cyanColor; // 0.0, 1.0, 1.0 RGB
+ (UIColor *)yellowColor; // 1.0, 1.0, 0.0 RGB
+ (UIColor *)magentaColor; // 1.0, 0.0, 1.0 RGB
+ (UIColor *)orangeColor; // 1.0, 0.5, 0.0 RGB
+ (UIColor *)purpleColor; // 0.5, 0.0, 0.5 RGB
+ (UIColor *)brownColor; // 0.6, 0.4, 0.2 RGB
+ (UIColor *)clearColor; // 透明色
按鈕
- 自定義按鈕:調整內部子控件的frame
- 方式1:實現titleRectForContentRect:和imageRectForContentRect:方法,分別返回titleLabel和imageView的frame
- 方式2:在layoutSubviews方法中設置
- 內邊距
// 設置按鈕內容的內邊距(影響到imageView和titleLabel)
@property(nonatomic) UIEdgeInsets contentEdgeInsets;
// 設置titleLabel的內邊距(影響到titleLabel)
@property(nonatomic) UIEdgeInsets titleEdgeInsets;
// 設置imageView的內邊距(影響到imageView)
@property(nonatomic) UIEdgeInsets imageEdgeInsets;
圖片拉伸
- iOS5之前
// 只拉伸中間的1x1區域
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;
- iOS5開始
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode;
拷貝(copy)
- 實現拷貝的方法有2個
- copy:返回不可變副本
- mutableCopy:返回可變副本
- 普通對象實現拷貝的步驟
- 遵守NSCopying協議
- 實現-copyWithZone:方法
- 創建新對象
- 給新對象的屬性賦值
copy
KVC
- 全稱:Key Value Coding(鍵值編碼)
- 賦值
// 能修改私有成員變量
- (void)setValue:(id)value forKey:(NSString *)key;
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
- 取值
// 能取得私有成員變量的值
- (id)valueForKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
KVO
- 全稱:Key Value Observing(鍵值監聽)
- 作用:監聽模型的屬性值改變
- 步驟
- 添加監聽器
// 利用b對象來監聽a對象name屬性的改變
[a addObserver:b forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"test"];
- 在監聽器中實現監聽方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"%@ %@ %@ %@", object, keyPath, change, context);
}
代理的使用步驟
- 定義一份代理協議
- 協議名字的格式一般是:類名 + Delegate
- 比如UITableViewDelegate
- 代理方法細節
- 一般都是@optional
- 方法名一般都以類名開頭
- 比如
- (void)scrollViewDidScroll:
- 比如
- 一般都需要將對象本身傳出去
- 比如tableView的方法都會把tableView本身傳出去
- 必須要遵守NSObject協議
- 比如
@protocol XMGWineCellDelegate <NSObject>
- 比如
- 協議名字的格式一般是:類名 + Delegate
- 聲明一個代理屬性
- 代理的類型格式:id<協議> delegate
@property (nonatomic, weak) id<XMGWineCellDelegate> delegate;
- 設置代理對象
xxx.delegate = yyy;
- 代理對象遵守協議,實現協議里面相應的方法
- 當控件內部發生了一些事情,就可以調用代理的代理方法通知代理
- 如果代理方法是@optional,那么需要判斷方法是否有實現
if ([self.delegate respondsToSelector:@selector(wineCellDidClickPlusButton:)]) {
[self.delegate wineCellDidClickPlusButton:self];
}
iOS監聽某些事件的方法
- 通過addTarget:
- 只有繼承自UIControl的控件,才有這個功能
- UIControlEventTouchUpInside : 點擊事件(UIButton)
- UIControlEventValueChanged : 值改變事件(UISwitch、UISegmentControl、UISlider)
- UIControlEventEditingChanged : 文字改變事件(UITextField)
- 通知(NSNotificationCenter\NSNotification)
- 任何對象之間都可以傳遞消息
- 使用范圍
- 1個對象可以發通知給N個對象
- 1個對象可以接受N個對象發出的通知
- 必須得保證通知的名字在發出和監聽時是一致的
- KVO
- 僅僅是能監聽對象屬性的改變(靈活度不如通知和代理)
- 代理delegate
- 只有擁有delegate屬性的控件,才有這個功能
- 使用范圍
- 1個對象只能設置一個代理(假設這個對象只有1個代理屬性)
- 1個對象能成為多個對象的代理
- 比
通知
規范 - 建議使用
代理
多于通知
數據刷新(UITableView數據)
1.全局刷新(最常用的方法)
[self.tableView reloadData];
2.局部刷新
- 2.1 增加模型數組
//在index插入一個模型數據
-(void)insertObject:(id)anObject atIndex:(NSUInteger)index;
//添加模型
- (void)addObject:(id)anObject;
- 2.1.1 增加數據后刷新
-(void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- 2.2 刪除模型數組
//移除最后一個模型
- (void)removeLastObject;
//移除index位置的的數據模型
- (void)removeObjectAtIndex:(NSUInteger)index;
//用anObject取代index位置的模型
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
- 2.2.1 刪除數據后刷新
-(void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- 2.3 更改模型數組
-(void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
左滑刪除功能
//只要實現了這個方法,左滑出現Delete按鈕的功能就有了;點擊了“左滑出現的Delete按鈕”也會調用這個方法
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
//修改右側Delete的文字
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
- 2.左滑出現多個按鈕
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *action0 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"關注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"點擊了關注");
// 收回左滑出現的按鈕(退出編輯模式)
tableView.editing = NO;
}];
UITableViewRowAction *action1 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"刪除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
[self.wineArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}];
return @[action1, action0];
}
批量刪除功能
//開啟批量刪除功能
[self.tableView setEditing:!self.tableView.isEditing animated:YES];
//開啟批量刪除功能后,可以編輯
self.tableView.allowsMultipleSelectionDuringEditing = YES;