iOS深刻學習(再談block)

以前寫過一篇博客,把Block跟delegate類比,說明了使用block,能夠經過更少的代碼實現代理的功能。那篇博客將block定義爲類的property。函數

過了這麼長時間,對於block的內容有了不少的遺忘,果真block的語法比較操蛋,容易遺忘,仍是看看http://fuckingblocksyntax.com/,複習一下操蛋的block語法,我翻譯以下,atom

(1)block做爲本地變量(local variable)spa

returnType (^blockName)(parameterTypes) = ^returnType(parameters){...};.net

(2)block做爲類的成員屬性(@property)
翻譯

@property (nonatomic, copy) returnType (^blockName)(parameters);代理

這時候能夠類比delegate,實現代理功能。code

(3)block做爲函數參數(method parameter)對象

- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
blog

調用包括block參數的函數,事件

[someObject somethodThatTakesABlock:^returnType(parameters){...}];

(4)使用typedef定義block類型

typedef returnType (^TypeName)(parameterTypes);

TypeName blockName = ^returnType(parameters){...};

上面的內容翻譯自fuckblocksyntax,你們忘了block語法的時候能夠反覆的看看。


Block的使用舉例,

(1)做爲本地變量

int (^Mutiply)(int,int) = ^(int num1,int num2){

    return num1*num2;

};

block能夠訪問局部變量,可是不能修改,不然會編譯報錯,

int mutiplier = 7;

int (^myBlock)(int) = ^(int num){

    mutiplier++;//編譯報錯

    return num*mutiplier;

};

若是要在block內部修改局部變量,則須要使用__block來修飾該局部變量,以下,

__block int mutiplier = 7;

int (^myBlock)(int) = ^(int num){

    mutiplier++;//編譯不會報錯

    return num*mutiplier;

};

(2)做爲函數參數使用

做爲函數的參數,block某種意義上替代了回調函數或者delegate,當函數調用的時候,假設某個事件發生,這時候block裏面的內容就會運行。這樣有利於代碼的整合和閱讀,不須要處處去實現委託方法了。

Block做爲函數參數,到底該怎麼寫代碼呢?今天(2014.05.09)晚上忽然想明白,只要堅決的把Block當作delegate,一切就很簡單了,咱們先看看delegate做爲參數,是怎麼寫的吧,以下代碼,

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"點擊Cell" delegate:self cancelButtonTitle:@"肯定" otherButtonTitles:nil, nil];

[alert show];

這裏是初始化一個alert而且讓alert彈出,讓咱們看看初始化的-(void)initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:是怎麼定義的吧,以下代碼,

- (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id /*<UIAlertViewDelegate>*/)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;//Xcode中複製過來的

我特別把delegate參數用紅色註明,因此是否是有了一點怎樣去定義block做爲參數的靈感,下面我就寫完整的代碼,分享我本身的經驗吧,

首先,仍是要說一個場景,自定義的cell上面有一個Button,點擊Button,調用在ViewController中的-(void)OperateLog:方法,

很少說了,上代碼,

ImageTableViewCell.h file

typedef void (^BtnBlock)();//定義一個block

@interface ImageTableViewCell:UITableViewCell

{

    BtnBlock _btnBlock;//定義一個block成員變量

}

//下面是兩個xib拖動的控件

@property (nonatomic, strong) IBOutlet UIButton *btn;

@property (nonatomic, strong) IBOutlet UIIageView *imgView;

- (void)configureCell:(UITableViewCellStyle)style Block:(BtnBlock)block reuseIdentifier:(NSString *)reuseIdentifier;

//點擊Button觸發的方法

- (IBAction)btnClicked:(id)sender;

@end

ImageTableViewCell.m file

@implementation ImageTableViewCell

//...省略無關代碼

- (void)configureCell:(UITableViewCellStyle)style Block:(BtnBlock)block reuseIdentifier:(NSString *)reuseIdentifier

{

    //...省略不相干代碼

    _btnBlock = block;

}

- (IBAction)btnClicked:(id)sender

{

    if(_btnBlock)

    {

        _btnBlock();

    }

}


ViewController.m file

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    NSString *simpleIdentify = @"UITableViewCellIdentify";

    ImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleIdentify];

    if (!cell) {

        //將Custom.xib中的全部對象載入

        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ImageTableViewCell" owner:self options:nil];

        //第一個對象就是CustomCell了

        cell = [nib objectAtIndex:0];

        [cell configureCell:UITableViewCellStyleDefault Block:^{

            [self OperateLog];

        } reuseIdentifier:simpleIdentify];

    }

    return cell;

}

//button點擊,最終傳遞到OperateLog方法,至關於代理方法吧

- (void)OperateLog

{

    NSLog(@"點擊了cell上面的Button");

}


這篇博客和以前的博客,請有心人必定要仔細看明白,若是有什麼疑問我必定詳細解答,由於我以爲Block是我本身最花了時間研究的,若是其餘的人可以經過個人博客而漲了姿式的話,我確定是很開心的。還要提醒有心人,看懂了的人天然明白這篇博客的精髓和犀利

我建了一個iOS交流羣188647173,歡迎各位前來交流。

相關文章
相關標籤/搜索