IOS 學習筆記 2015-03-27 我理解的OC-代理模式,2015-03-27oc-
案例1
KCButton.h//// KCButton.h// Protocol&Block&Category//// Created by Kenshin Cui on 14-2-2.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#import <Foundation/Foundation.h>@class KCButton;//一個協議可以擴充另一個協議,例如KCButtonDelegate擴充了NSObject協議@protocol KCButtonDelegate <NSObject>@required //@required修飾的方法必須實現-(void)onClick:(KCButton *)button;@optional //@optional修飾的方法是可選實現的-(void)onMouseover:(KCButton *)button;-(void)onMouseout:(KCButton *)button;@end@interface KCButton : NSObject#pragma mark - 屬性#pragma mark 代理屬性,同時約定作為代理的對象必須實現KCButtonDelegate協議@property (nonatomic,retain) id<KCButtonDelegate> delegate;#pragma mark - 公用方法#pragma mark 點擊方法-(void)click;@end
KCButton.m//// KCButton.m// Protocol&Block&Category//// Created by Kenshin Cui on 14-2-2.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#import "KCButton.h"@implementation KCButton-(void)click{ NSLog(@"Invoke KCButton's click method."); //判斷_delegate執行個體是否實現了onClick:方法(注意方法名是"onClick:",後面有個:) //避免未實現ButtonDelegate的類也作為KCButton的監聽 if([_delegate respondsToSelector:@selector(onClick:)]){ [_delegate onClick:self]; }}@endMyListener.h//// MyListener.h// Protocol&Block&Category//// Created by Kenshin Cui on 14-2-2.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#import <Foundation/Foundation.h>@class KCButton;@protocol KCButtonDelegate;@interface MyListener : NSObject<KCButtonDelegate>-(void)onClick:(KCButton *)button;@endMyListener.m//// MyListener.m// Protocol&Block&Category//// Created by Kenshin Cui on 14-2-2.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#import "MyListener.h"#import "KCButton.h"@implementation MyListener-(void)onClick:(KCButton *)button{ NSLog(@"Invoke MyListener's onClick method.The button is:%@.",button);}@endmain.m//// main.m// Protocol&Block&Category//// Created by Kenshin Cui on 14-2-2.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#import <Foundation/Foundation.h>#import "KCButton.h"#import "MyListener.h"int main(int argc, const char * argv[]) { @autoreleasepool { KCButton *button=[[KCButton alloc]init]; MyListener *listener=[[MyListener alloc]init]; button.delegate=listener; [button click]; /* 結果: Invoke KCButton's click method. Invoke MyListener's onClick method.The button is:<KCButton: 0x1001034c0>. */ } return 0;}
我們通過例子類比了一個按鈕的點擊過程,有點類似於Java中事件的實現機制。通過這個例子我們需要注意以下幾點內容:id可以表示任何一個ObjC物件類型,類型後面的”<協議名>“用於約束作為這個屬性的對象必須實現該協議(注意:使用id定義的物件類型不需要加“*”);MyListener作為事件觸發者,它實現了KCButtonDelegate代理(在ObjC中沒有命名空間和包的概念,通常通過首碼進行類的劃分,“KC”是我們自訂的首碼)在.h檔案中如果使用了另一個檔案的類或協議我們可以通過@class或者@protocol進行聲明,而不必匯入這個檔案,這樣可以提高編譯效率(注意有些情況必須使用@class或@protocol,例如上面KCButton.h中上面聲明的KCButtonDelegate協議中用到了KCButton類,而此檔案下方的KCButton類聲明中又使用了KCButtonDelegate,從而形成在一個檔案中互相參考關聯性,此時必須使用@class或者@protocol聲明,否則編譯階段會報錯),但是在.m檔案中則必須匯入對應的類聲明檔案或協議檔案(如果不匯入雖然語法檢查可以通過但是編譯連結會報錯);使用respondsToSelector方法可以判斷一個對象是否實現了某個方法(需要注意方法名不是”onClick”而是“onClick:”,冒號也是方法名的一部分);屬性中的(nonatomic,retain)不是這篇文章的重點,在接下來的文章中我們會具體介紹。
案例2
//// WPContactsViewController.h// OC-UI-表單-儲存格//// Created by wangtouwang on 15/3/26.// Copyright (c) 2015年 wangtouwang. All rights reserved.//#import <UIKit/UIKit.h>@interface WPContactsViewController : UIViewController{ UITableView *_tableView;//表單UI控制項 NSMutableArray *_mutableArrayContacts;//連絡人集合模型 NSIndexPath *_selectedIndexPath;//當前選中的組和行}@end
//// WPContactsViewController.m// OC-UI-表單-儲存格//// Created by wangtouwang on 15/3/26.// Copyright (c) 2015年 wangtouwang. All rights reserved.//#import "WPContactsViewController.h"#import "WPContacts.h"#import "WPContactsGroup.h"@interface WPContactsViewController ()<UITableViewDataSource,UITableViewDelegate,UIAlertViewDelegate>@end@implementation WPContactsViewController- (void)viewDidLoad { [super viewDidLoad]; //初始化資料 [self initObjectData]; //建立一個分組樣式的UITableView _tableView=[[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; //設定資料來源,注意必須實現對應的UITableViewDataSource協議 _tableView.dataSource=self; //設定代理 _tableView.delegate=self; [self.view addSubview:_tableView];}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}#pragma mark 載入資料-(void)initObjectData{ _mutableArrayContacts=[[NSMutableArray alloc]init]; WPContacts *contact1=[WPContacts initStaticWithFirstName:@"Cui" andLastName:@"Kenshin" andPhoneNumber:@"18500131234"]; WPContacts *contact2=[WPContacts initStaticWithFirstName:@"Cui" andLastName:@"Tom" andPhoneNumber:@"18500131237"]; WPContactsGroup *group1=[WPContactsGroup initStaticWithName:@"C" andDescript:@"With names beginning with C" andConcats:[NSMutableArray arrayWithObjects:contact1,contact2, nil]]; [_mutableArrayContacts addObject:group1]; WPContacts *contact3=[WPContacts initStaticWithFirstName:@"Dui" andLastName:@"JACK" andPhoneNumber:@"13712133321"]; WPContacts *contact4=[WPContacts initStaticWithFirstName:@"Dui" andLastName:@"LUCY" andPhoneNumber:@"13712133322"]; WPContactsGroup *group2=[WPContactsGroup initStaticWithName:@"D" andDescript:@"With names beginning with D" andConcats:[NSMutableArray arrayWithObjects:contact3,contact4, nil]]; [_mutableArrayContacts addObject:group2]; }#pragma mark 返回分組數-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ NSLog(@"計算分組數"); return _mutableArrayContacts.count;}#pragma mark 返回每組行數- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ NSLog(@"計算每組(組%lu)行數",(unsigned long)section);// WPContactsGroup *group1 = _mutableArrayContacts[section]; return ((WPContactsGroup *)_mutableArrayContacts[section])._concats.count;}#pragma mark返回每行的儲存格- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSLog(@"產生儲存格(組:%lu,行%lu)",(unsigned long)indexPath.section,(unsigned long)indexPath.row); WPContactsGroup *group= _mutableArrayContacts[indexPath.section]; WPContacts *contacts = group._concats[indexPath.row]; UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil]; cell.textLabel.text=[contacts getName]; cell.detailTextLabel.text = [contacts _phoneNumber]; return cell;}#pragma mark 返回每組頭標題名稱- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ NSLog(@"產生組(組%lu)名稱",(unsigned long)section); WPContactsGroup *group = _mutableArrayContacts[section]; return group._name;}#pragma mark 返回每組尾部說明- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{ NSLog(@"產生尾部(組%lu)詳情",(unsigned long)section); return ((WPContactsGroup *)_mutableArrayContacts[section])._descript;}#pragma mark 產生索引- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{ NSLog(@"產生組索引"); NSMutableArray *indexs = [[NSMutableArray alloc] init]; for (WPContactsGroup *group in _mutableArrayContacts) { [indexs addObject:group._name]; } return indexs;}#pragma mark 設定分組標題高度- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ NSLog(@"設定分組標題高度"); return 25;}#pragma mark 設定分組尾部內容高度- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ NSLog(@"設定分組尾部內容高度"); return 20;}#pragma mark 設定每行高度- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ NSLog(@"設定每行高度"); return 30;}#pragma mark 複寫設定點擊行觸發事件(複寫的方法是在TableViewDelegate協議中已有,回調)-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSLog(@"觸發我吧"); _selectedIndexPath=indexPath; //擷取儲存格封裝的對象WPContacts WPContacts *contacts = ((WPContactsGroup *)_mutableArrayContacts[indexPath.section])._concats[indexPath.row]; //初始化彈出框 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"System Info" message:[contacts getName] delegate:self cancelButtonTitle:@"Cancle" otherButtonTitles:@"OK", nil]; //設定視窗樣式 alertView.alertViewStyle=UIAlertViewStylePlainTextInput; //擷取文字框 UITextField *textFild = [alertView textFieldAtIndex:0]; //設定文字框內容 textFild.text = contacts._phoneNumber; //顯示視窗 [alertView show];}#pragma mark 設定彈出框後續按鈕事件 複寫UIAlerViewDelegate協議 的點擊按鈕 clickedButtonAtIndex方法- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ NSLog(@"設定彈出框後續按鈕事件 clickedButtonAtIndex"); if (buttonIndex==1) { //擷取文字框內容 NSString *phoneNumber = [alertView textFieldAtIndex:0].text; //擷取選中的UITableViewCell 封裝的對象 WPContacts *contacts = ((WPContactsGroup *)_mutableArrayContacts[_selectedIndexPath.section])._concats[_selectedIndexPath.row]; contacts._phoneNumber = phoneNumber; NSArray *indexPaths=@[_selectedIndexPath];//需要局部重新整理的儲存格的組、行 //此處最佳化 將全域跟新 該變到 選擇行 局部更新 [_tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft]; //[_tableView reloadData]; }}@end