UITableViewCell控件空間構造
- cell的子控件是contentView,contentView的子控件是imageView、textLabel、detailTextLabel
- 可以通過移動contentView,顯示刪除按鈕,點擊刪除按鈕便可實現刪除對應的cell
- 在代碼方式制作等高cell中,cell可以通過AutoLayOut(約束)在layoutSubView或initWithStyle方法中設置子控件的位置
-
靜態cell的數據是死的且可以自定義,動態cell數據顯示源自模型數據庫
Snip20170205_143.png -
設置tableView每 cell的度,默認是44
Snip20170205_136.png
Snip20170205_137.png
UITableView
-
表頂部圖片顯示:將圖片控件添加到表頭視圖上
Snip20170205_144.png
self.tableView.tableHeaderView
- 凡是遵守UITableViewDataSource協議的OC對象,都可以是UITableView的數據源
-
Control負責初始化Model,并將Model傳遞給View去解析展示
Snip20170205_140.png
Cell的重用原理
- 重用原理:
- 當滾動列表時,部分UITableViewCell會移出窗口,UITableView會將窗口外的UITableViewCell放入一個對象池中,等待重用。當UITableView要求dataSource返回UITableViewCell時,dataSource會先查看這個對象池,如果池中有未使用的UITableViewCell,dataSource會用新的數據配置這個UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免創建新對象
- 解決方案:
- UITableViewCell有個NSString *reuseIdentifier屬性,可以在初始化UITableViewCell的時候傳入一個特定的字符串標識來設置reuseIdentifier(一般用UITableViewCell的類名)。當UITableView要求dataSource返回UITableViewCell時,先通過一個字符串標識到對象池中查找對應類型的UITableViewCell對象,如果有,就重用,如果沒有,就傳入這個字符串標識來初始化一個UITableViewCell對象
Cell的重用代碼
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 1.定義一個cell的標識
static NSString *ID = @”cell";
// 2.從緩存池中取出cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 3.如果緩存池中沒有cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
通過代碼自定義cell(cell的高度不一致)
- 新建一個繼承自UITableViewCell的類
- 重寫initWithStyle:reuseIdentifier:方法
- 添加所有需要顯示的子控件(不需要設置子控件的數據和frame, 子控件要添加到contentView中)
- 進行子控件一次性的屬性設置(有些屬性只需要設置一次, 比如字體固定的圖片)
- 提供2個模型
- 數據模型: 存放文字數據\圖片數據
- frame模型: 存放數據模型\所有子控件的frame\cell的高度
- cell擁有一個frame模型(不要直接擁有數據模型)
- 重寫frame模型屬性的setter方法: 在這個方法中設置子控件的顯示數據和frame
- frame模型數據的初始化已經采取懶加載的方式(每一個cell對應的frame模型數據只加載一次)
UITextField
- 通過UITextField的代理方法能夠監聽鍵盤最右下角按鈕的點擊
- 成為UITextField的代理
self.textField.delegate = self;
- 遵守UITextFieldDelegate協議,實現代理方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
- 在UITextField左邊放一個view
self.textField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)];
self.textField.leftViewMode = UITextFieldViewModeAlways;
索引條
- 設置索引條上 字顏
self.tableView.sectionIndexColor = [UIColor redColor];
- 設置索引條的背景顏
self.tableView.sectionIndexBackgroundColor = [UIColor blackColor];
- 返回每 組的索引標題(數組中都是NSString對象)
- (NSArray<NSString *>*)sectionIndexTitlesForTableView:(UITableView *)tableView {
}
Frame自定義不等高的cell
- 給模型增加frame數據
- 所有子控件的frame
- cell的高度
@interface XMGStatus : NSObject
/** 頭像的frame */
@property (nonatomic, assign) CGRect iconFrame;
// .....
/** cell的高度 */
@property (nonatomic, assign) CGFloat cellHeight;
@end
- 重寫模型cellH屬性的get方法
- (CGFloat)cellHeight{
if (_cellHeight == 0) {
// ... 計算所有子控件的frame、cell的高度
}
return _cellHeight;
}
- 在控制器中
- 實現一個返回cell高度的代理方法
- 在這個方法中返回indexPath位置對應cell的高度
/**
返回每一行cell的具體高度
*/
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
XMGStatus *status = self.statuses[indexPath.row];
return status.cellH;
}
- 給cell傳遞模型數據
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *ID = @"status";
// 訪問緩存池
XMGStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 設置數據(傳遞模型數據)
cell.status = self.statuses[indexPath.row];
return cell;
}
- 新建一個繼承自UITableViewCell的子類,比如XMGStatusCell
@interface XMGStatusCell : UITableViewCell
@end
- 在XMGStatusCell.m文件中
- 重寫-initWithStyle:reuseIdentifier:方法
- 在這個方法中添加所有可能顯示的子控件
- 給子控件做一些初始化設置(設置字體、文字顏色等)
/**
* 在這個方法中添加所有的子控件
*/
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// ......
}
return self;
}
- 在XMGStatusCell.h文件中提供一個模型屬性,比如XMGStatus模型
@class XMGStatus;
@interface XMGStatusCell : UITableViewCell
/** 團購模型數據 */
@property (nonatomic, strong) XMGStatus *status;
@end
- 在XMGStatusCell.m文件中重寫模型屬性的set方法
- 在set方法中給子控件設置模型數據
- (void)setStatus:(XMGStatus *)status{
_status = status;
// .......
}
- 重寫-layoutSubviews方法
- 一定要調用[super layoutSubviews]
- 在這個方法中設置所有子控件的frame
/**
* 在這個方法中設置所有子控件的frame
*/
- (void)layoutSubviews{
[super layoutSubviews];
// ......
}
AutoLayOut自定義等高的cell
- 新建一個繼承自UITableViewCell的子類,比如XMGTgCell
@interface XMGTgCell : UITableViewCell
@end
- 在XMGTgCell.m文件中
- 重寫-initWithStyle:reuseIdentifier:方法
- 在這個方法中添加所有的子控件
- 給子控件做一些初始化設置(設置字體、文字顏色等)
- 添加子控件的完整約束
/**
* 在這個方法中添加所有的子控件
*/
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// ......
}
return self;
}
- 在XMGTgCell.h文件中提供一個模型屬性,比如XMGTg模型
@class XMGTg;
@interface XMGTgCell : UITableViewCell
/** 團購模型數據 */
@property (nonatomic, strong) XMGTg *tg;
@end
- 在XMGTgCell.m中重寫模型屬性的set方法
- 在set方法中給子控件設置模型數據
- (void)setTg:(XMGTg *)tg{
_tg = tg;
// .......
}
- 在控制器中
- 注冊cell的類型
[self.tableView registerClass:[XMGTgCell class] forCellReuseIdentifier:ID];
- 給cell傳遞模型數據
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 訪問緩存池
XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 設置數據(傳遞模型數據)
cell.tg = self.tgs[indexPath.row];
return cell;
}
字典轉模型第三方框架
- Mantle
- 所有模型都必須繼承自MTModel
- JSONModel
- 所有模型都必須繼承自JSONModel
- MJExtension
- 不需要強制繼承任何其他類
Frame(微博)自定義等高的cell
- 新建一個繼承自UITableViewCell的子類,比如XMGTgCell
@interface XMGTgCell : UITableViewCell
@end
- 在XMGTgCell.m文件中
- 重寫-initWithStyle:reuseIdentifier:方法
- 在這個方法中添加所有的子控件
- 給子控件做一些初始化設置(設置字體、文字顏色等)
/**
* 在這個方法中添加所有的子控件
*/
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// ......
}
return self;
}
- 重寫-layoutSubviews方法
- 一定要調用[super layoutSubviews]
- 在這個方法中計算和設置所有子控件的frame
/**
* 在這個方法中計算所有子控件的frame
*/
- (void)layoutSubviews{
[super layoutSubviews];
// ......
}
- 在XMGTgCell.h文件中提供一個模型屬性,比如XMGTg模型
@class XMGTg;
@interface XMGTgCell : UITableViewCell
/** 團購模型數據 */
@property (nonatomic, strong) XMGTg *tg;
@end
- 在XMGTgCell.m中重寫模型屬性的set方法
- 在set方法中給子控件設置模型數據
- (void)setTg:(XMGTg *)tg{
_tg = tg;
// .......
}
- 在控制器中
- 注冊cell的類型
[self.tableView registerClass:[XMGTgCell class] forCellReuseIdentifier:ID];
- 給cell傳遞模型數據
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 訪問緩存池
XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 設置數據(傳遞模型數據)
cell.tg = self.tgs[indexPath.row];
return cell;
}
StoryBoard(微博)自定義等高的cell
- 新建一個繼承自
UITableViewCell
的子類,比如XMGTgCell
@interface XMGTgCell : UITableViewCell
@end
- 在storyboard文件中,找到UITableView里面的cell(動態cell)
- 修改cell的class為XMGTgCell
- 綁定循環利用標識
- 添加子控件,設置子控件約束
- 將子控件連線到類擴展中
@interface XMGTgCell()
@property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UILabel *priceLabel;
@property (weak, nonatomic) IBOutlet UILabel *buyCountLabel;
@end
- 在XMGTgCell.h文件中提供一個模型屬性,比如XMGTg模型
@class XMGTg;
@interface XMGTgCell : UITableViewCell
/** 團購模型數據 */
@property (nonatomic, strong) XMGTg *tg;
@end
- 在XMGTgCell.m中重寫模型屬性的set方法
- 在set方法中給子控件設置模型數據
- (void)setTg:(XMGTg *)tg{
_tg = tg;
// .......
}
- 在控制器中
- 給cell傳遞模型數據
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *ID = @"tg";
// 訪問緩存池
XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 設置數據(傳遞模型數據)
cell.tg = self.tgs[indexPath.row];
return cell;
}
xib自定義等高cell
- 新建一個繼承自
UITableViewCell
的子類,比如XMGTgCell
@interface XMGTgCell : UITableViewCell
@end
- 新建一個xib文件(文件名最好跟類名一致,比如XMGTgCell.xib)
- 修改cell的class為XMGTgCell
- 綁定循環利用標識
- 添加子控件,設置子控件約束
- 將子控件連線到類擴展中
@interface XMGTgCell()
@property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UILabel *priceLabel;
@property (weak, nonatomic) IBOutlet UILabel *buyCountLabel;
@end
- 在XMGTgCell.h文件中提供一個模型屬性,比如XMGTg模型
@class XMGTg;
@interface XMGTgCell : UITableViewCell
/** 團購模型數據 */
@property (nonatomic, strong) XMGTg *tg;
@end
- 在XMGTgCell.m中重寫模型屬性的set方法
- 在set方法中給子控件設置模型數據
- (void)setTg:(XMGTg *)tg{
_tg = tg;
// .......
}
- 在控制器中
- 注冊xib文件
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGTgCell class]) bundle:nil] forCellReuseIdentifier:ID];
- 給cell傳遞模型數據
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 訪問緩存池
XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 設置數據(傳遞模型數據)
cell.tg = self.tgs[indexPath.row];
return cell;
}
StoryBoard(微博)-自定義不等的cell
- 對比自定義等高cell,需要幾個額外的步驟(iOS8開始才支持)
- 添加子控件和contentView之間的間距約束
- 設置tableViewCell的真實行高和估算行高
//告訴tableView所有cell的真實高度是自動計算(根據設置的約束來計算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
//告訴tableView所有cell的估算高度
self.tableView.estimatedRowHeight = 44;
- 如果要支持iOS8之前
- 如果cell內部有自動換行的label,需要設置preferredMaxLayoutWidth屬性
-(void)awakeFromNib
{
//手動設置文字的最大寬度(目的是:讓label知道自己文字的最大寬度,進而能夠計算出自己的frame)
self.text_label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}
- 設置tableView的cell估算高度
//告訴tableView所有cell的估算高度(設置了估算高度,就可以減少tableView:heightForRowAtIndexPath:方法的調用次數)
self.tableView.estimatedRowHeight = 200;
- 在代理方法中計算cell的高度
XMGStatusCell *cell;
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//創建一個臨時的cell(cell的作用:根據模型數據布局所有的子控件,進而計算出cell的高度)
if (!cell) {
cell = [tableView dequeueReusableCellWithIdentifier:ID];
}
//設置模型數據
cell.status = self.statuses[indexPath.row];
return cell.height;
}
-(CGFloat)height{
//強制布局cell內部的所有子控件(label根據文字多少計算出自己最真實的尺寸)
[self layoutIfNeeded];
//計算cell的高度
if (self.status.picture) {
return CGRectGetMaxY(self.pictureImageView.frame) + 10;
} else {
return CGRectGetMaxY(self.text_label.frame) + 10;
}
}
數據刷新
添加數據
刪除數據
更改數據
全局刷新方法(最常用)
[self.tableView reloadData];
//屏幕上的所有可視的cell都會刷新一遍
-
局部刷新方法
- 添加數據
NSArray *indexPaths = @[
[NSIndexPath indexPathForRow:0 inSection:0],
[NSIndexPath indexPathForRow:1 inSection:0]
];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
- 刪除數據
NSArray *indexPaths = @[
[NSIndexPath indexPathForRow:0 inSection:0],
[NSIndexPath indexPathForRow:1 inSection:0]
];
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationMiddle];
- 更新數據(沒有添加和刪除數據,僅僅是修改已經存在的數據)
NSArray *indexPaths = @[
[NSIndexPath indexPathForRow:0 inSection:0],
[NSIndexPath indexPathForRow:1 inSection:0]
];
[self.tableView relaodRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationMiddle];
-
左滑出現刪除按鈕
- 需要實現tableView的代理方法
/**
*只要實現了這個方法,左滑出現Delete按鈕的功能就有了
*點擊了“左滑出現的Delete按鈕”會調用這個方法
*/
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
//刪除模型
[self.wineArray removeObjectAtIndex:indexPath.row];
//刷新
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}
/**
*修改Delete按鈕文字為“刪除”
*/
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
return @"刪除";
}
左滑出現N個按鈕
需要實現tableView的代理方法
/**
*只要實現了這個方法,左滑出現按鈕的功能就有了
(一旦左滑出現了N個按鈕,tableView就進入了編輯模式, tableView.editing = YES)
*/
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
}
/**
*左滑cell時出現什么按鈕
*/
- (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.tabelView.editing = YES;
[self.tableView setEditing:YES animated:YES];
//默認情況下,進入編輯模式時,左邊會出現一排紅色的“減號”按鈕
- 在編輯模式中多選
//編輯模式的時候可以多選
self.tableView.allowsMultipleSelectionDuringEditing = YES;
//進入編輯模式
[self.tableView setEditing:YES animated:YES];
//獲得選中的所有行
self.tableView.indexPathsForSelectedRows;
代理的使用步驟
- 定義一份代理協議
- 協議名字的格式一般是:類名+ Delegate
- 比如UITableViewDelegate
- 設計代理的細節
- 一般都是@optional(讓代理可以有選擇性去實現一些代理方法)
- 方法名一般都以類名開頭
- 比如- (void)scrollViewDidScroll:
- 一般都需要將對象本身傳出去
- 比如tableView的代理方法都會把tableView本身傳出去
必須要遵守NSObject協議(基協議)
比如@protocol XMGWineCellDelegate <NSObject>
-
聲明一個代理屬性
- 代理的類型格式:id<協議> delegate
@property (nonatomic, weak) id<XMGWineCellDelegate> delegate;
設置代理對象
代理對象遵守協議,實現協議里面相應的方法
當控件內部發生了一些事情,就可以調用代理的代理方法通知代理
- 如果代理方法是@optional,那么需要判斷方法是否有實現,直接調用可能會報錯
if ([self.delegate respondsToSelector:@selector(wineCellDidClickPlusButton:)]) {
[self.delegate wineCellDidClickPlusButton:self];
}
iOS監聽某些事件的方法
- 通知(NSNotificationCenter\NSNotification)
- 任何對象之間都可以傳遞消息
- 使用范圍
- 1個對象可以發通知給多個對象
- 1個對象可以接受多個對象發出的通知
- 要求:必須得保證通知的名字在發出和監聽時是一致的
- KVO
- 僅僅是能監聽對象屬性的改變(靈活度不如通知和代理)
- 代理
- 使用范圍
- 1個對象只能設置一個代理(假設這個對象只有1個代理屬性)
- 1個對象能成為多個對象的代理
- 如何選擇?
- 代理比通知規范
- 建議使用代理多于通知,能使用代理盡量使用代理
通知
-
基本概念
每一個應用程序都有一個通知中心(NSNotificationCenter)實例,專門負責協助不同對象之間的消息通信
任何一個對象都可以向通知中心發布通知(NSNotification),描述自己在做什么。其他感興趣的對象(Observer)可以申請在某個特定通知發布時(或在某個特定的對象發布通知時)收到這個通知
-
一個完整的通知一般包含3個屬性:
-(NSString *)name; // 通知的名稱
-(id)object; // 通知發布者(是誰要發布通知)
-(NSDictionary *)userInfo; // 一些額外的信息(通知發布者傳遞給通知接收者的信息內容)
-
初始化一個通知(NSNotification)對象
+(instancetype)notificationWithName:(NSString *)aName object:(id)anObject;
+(instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
-(instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;
-
發布通知
通知中心(NSNotificationCenter)提供了相應的方法來幫助發布通知
-
-(void)postNotification:(NSNotification *)notification;
- 發布一個notification通知,可在notification對象中設置通知的名稱、通知發布者、額外信息等
-
-(void)postNotificationName:(NSString *)aName object:(id)anObject;
- 發布一個名稱為aName的通知,anObject為這個通知的發布者
-
-(void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
- 發布一個名稱為aName的通知,anObject為這個通知的發布者,aUserInfo為額外信息
-
注冊通知監聽器
- 通知中心(NSNotificationCenter)提供了方法來注冊一個監聽通知的監聽器(Observer)
- -(void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
- observer:監聽器,即誰要接收這個通知
- aSelector:收到通知后,回調監聽器的這個方法,并且把通知對象當做參數傳入
- aName:通知的名稱。如果為nil,那么無論通知的名稱是什么,監聽器都能收到這個通知
- anObject:通知發布者。如果為anObject和aName都為nil,監聽器都收到所有的通知
- -(id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block;
- name:通知的名稱
- obj:通知發布者
- block:收到對應的通知時,會回調這個block
- queue:決定了block在哪個操作隊列中執行,如果傳nil,默認在當前操作隊列中同步執行
- 通知中心(NSNotificationCenter)提供了方法來注冊一個監聽通知的監聽器(Observer)
-
取消注冊通知監聽器
通知中心不會保留(retain)監聽器對象,在通知中心注冊過的對象,必須在該對象釋放前取消注冊。否則,當相應的通知再次出現時,通知中心仍然會向該監聽器發送消息。因為相應的監聽器對象已經被釋放了,所以可能會導致應用崩潰
-
通知中心提供了相應的方法來取消注冊監聽器
- -(void)removeObserver:(id)observer;
- -(void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
-
一般在監聽器銷毀之前取消注冊(如在監聽器中加入下列代碼):
- -(void)dealloc {
//[super dealloc]; 非ARC中需要調用此句
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- -(void)dealloc {
-
UIDevice通知
- UIDevice類提供了一個單粒對象,它代表著設備,通過它可以獲得一些設備相關的信息,比如電池電量值(batteryLevel)、電池狀態(batteryState)、設備的類型(model,比如iPod、iPhone等)、設備的系統(systemVersion)
通過[UIDevice currentDevice]可以獲取這個單粒對象
-
UIDevice對象會不間斷地發布一些通知,下列是UIDevice對象所發布通知的名稱常量:
- UIDeviceOrientationDidChangeNotification // 設備旋轉
- UIDeviceBatteryStateDidChangeNotification // 電池狀態改變
- UIDeviceBatteryLevelDidChangeNotification // 電池電量改變
- UIDeviceProximityStateDidChangeNotification // 近距離傳感器(比如設備貼近了使用者的臉部)
-
鍵盤通知
我們經常需要在鍵盤彈出或者隱藏的時候做一些特定的操作,因此需要監聽鍵盤的狀態
-
鍵盤狀態改變的時候,系統會發出一些特定的通知
- UIKeyboardWillShowNotification // 鍵盤即將顯示
- UIKeyboardDidShowNotification // 鍵盤顯示完畢
- UIKeyboardWillHideNotification // 鍵盤即將隱藏
- UIKeyboardDidHideNotification // 鍵盤隱藏完畢
- UIKeyboardWillChangeFrameNotification // 鍵盤的位置尺寸即將發生改變
- UIKeyboardDidChangeFrameNotification // 鍵盤的位置尺寸改變完畢
-
系統發出鍵盤通知時,會附帶一下跟鍵盤有關的額外信息(字典),字典常見的key如下:
- UIKeyboardFrameBeginUserInfoKey // 鍵盤剛開始的frame
- UIKeyboardFrameEndUserInfoKey // 鍵盤最終的frame(動畫執行完畢后)
- UIKeyboardAnimationDurationUserInfoKey // 鍵盤動畫的時間
- UIKeyboardAnimationCurveUserInfoKey // 鍵盤動畫的執行節奏(快慢)
-
通知和代理的選擇
-
共同點
- 利用通知和代理都能完成對象之間的通信
(比如A對象告訴D對象發生了什么事情, A對象傳遞數據給D對象)
- 利用通知和代理都能完成對象之間的通信
-
不同點
- 代理 : 1個對象只能告訴另1個對象發生了什么事情
- 通知 : 1個對象能告訴N個對象發生了什么事情, 1個對象能得知 N個對象發生了什么事情
-
- 總結
- 子類指向父類,需要強轉一下
- 擋在最前面的控件先處理事件。
- 給某個類使用kvo監聽,運行過程中系統默認會給他增加一個子類,這樣會增加性能消耗,isa指向真實類 [wine valueForKeyPath:”isa” ];或[wine class]可以獲取對象的類名 ,使用kvo方法valueForKeyPath可以獲取私有屬性的值
- 代理可以傳遞事件和數據,目的是解耦