iOS学习笔记(三十)————Block代码块

/ 0评 / 0

之前学过代理、通知,今天看一下iOS中很常用的另一项技术:block 代码块,其实就是回调传值~
来看一下基础的用法:

// block 代码块
// 1,基本的写法 声明 赋值 调用
// 2,typedef
// 3,循环引用

// 类型定义
typedef void(^DCBlock)(int a);

@interface BlockViewController : UIViewController{
    NSString * (^StrBlock) (int a);
    DCBlock block8;
}
// block 可以被声明成全局的 局部的 或者属性

@property (nonatomic, copy) NSString *(^StrBlock2) (int b);

@end

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
//    self.view.backgroundColor = [UIColor greenColor];
    
    
    NSMutableArray *array = nil;
    array = [[NSMutableArray alloc] init];
    [array addObject:@"1"];
    
    // block: 指针指向代码块
    
    // 1,声明了一个block指针
    // 返回值 (^指针的名字) (参数) = nil;
    void (^block2) (void) = nil;
    
    // 2,给这个指针赋值  给指针赋一段代码
    /*
     指针的名字 = ^(参数){
     具体的代码
     return 返回值;
     }
     */
    block2 = ^(void){
        NSLog(@"这事block2 中的代码");
    };
    
    // 3,使用这个block(让这个指针所保存的代码执行)
    block2();
    
    
    // 声明一个 有(两个int类型的参数,一个字符串类型的返回值)这样的block
    NSString * (^block3) (int a,int b) = nil;
    
    block3 = ^(int a,int b){
        int c = a + b;
        NSLog(@"c  %d",c);
        return [NSString stringWithFormat:@"%d",c];
    };
    
    NSLog(@"11111");
    NSString *str = block3(1,2);
    NSLog(@"str  %@",str);
    
    NSString *str2 = block3(2,3);
    NSLog(@"str2  %@",str2);
    
    // 小结:
    // 1,类似方法
    // 2,调用的时候 不需要什么对象
    // 3,格式上:声明 赋值 调用 格式要求很严格
    // block 指的是具有一定类型的一个指针 指向一段有一定格式的代码,并且这段代码可以被调用
    // 指针 指向(保存) 一段代码
    
    NSString * (^getPathBlock) (NSString *fileName) = nil;
    
    getPathBlock = ^(NSString *fileName){
        NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
        NSString *filePath = [NSString stringWithFormat:@"%@/%@",path,fileName];
        return filePath;
    };
    
    NSString *path = getPathBlock(@"a.txt");
    NSLog(@"path  %@",path);
    
    
    // 如果某一种格式的block在程序中 需要声明很多个,那么可以把这种类型的block 写成类型定义typedef
    
    void (^block4) (int a) = ^(int a){
        NSLog(@"这是block4  %d",a);
        NSLog(@"111");
    };
    block4(4);
    
    
    DCBlock block5 = ^(int a){
        NSLog(@"这事block5  %d",a);
    };
    block5(5);
    
    
    // 如果在一个block中 使用局部变量,那么block内部会把这个指针 复制 一份,
    // 在block内部给指针重新赋值,全局的可以,有__block描述的也可以,没有经过__block描述的局部变量不可以
    // 在吧block内部使用一个变量 ,全局的,局部的都可以
    
    // 如果必须在block内部给指针赋值
    // 1,把指针声明成全局的
    // 2,局部的就加__block
    __block NSMutableArray *array111 = nil;
    
    DCBlock block6 = ^(int a){
        NSLog(@"aaa  %d",a);
        
        array111 = [[NSMutableArray alloc] init];// 重新给指针赋值
        //        [array111 addObject:@"11"];// 使用指针
    };
    block6(6);
    
    NSLog(@"111111  %@",array111);
    
    
    // block中的循环引用
    // 在一个属性描述过的block中 使用对象,这些对象引用计数都会+1
    
    
    __block BlockViewController *otherSelf = self;
    
    self.StrBlock2 = ^(int b){
        NSLog(@"b  %d",b);
        //        [self test];
        [otherSelf test];
        return [NSString stringWithFormat:@"%d",b];
    };
    
    self.StrBlock2(4);
    
    
    // 由于给block赋一段代码的时候,block用的copy描述,然后block中使用过self  引用计数+1
    // 1什么时候可以减掉?
    // 当这个block被释放的时候 1会减掉
    // block什么时候被释放?
    // block被描述成属性了,属性在dealloc方法中释放
    // dealloc方法什么时候调用?
    // 当前类的对象(self)被释放时,dealloc才会调用
    // 当前类的对象什么时候会被释放?
    // self引用计数 = 0
    
    // 什么情况下会出现循环引用?
    // 1,这个block是属于谁的?  self
    // 2,是否在block中使用了这个对象
}

- (void)test{
    NSLog(@"test");
}

iOS的系统库中有很多地方都用到了block,我们使用的三方库中也很多都用到了,之前我们也看到过,而且苹果也是比较鼓励使用block的,举两个应用的例子

第一个:登录的例子

//首页,可能不需要登录就能看到
- (IBAction)comment:(id)sender {
    BOOL isLogin = NO;
    
    UIStoryboard* mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    
    if (!isLogin){
        
        // 模态一个登录界面
        LoginViewController *loginVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"LoginViewController"];
        
        loginVC.pushBlock = ^(void){
            CommentViewController *commentVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"CommentViewController"];
            [self.navigationController pushViewController:commentVC animated:YES];
        };

        [self presentViewController:loginVC animated:YES completion:nil];
    }else{
        // 直接push到评论界面

    }
}


//登录界面
@interface LoginViewController : UIViewController
//这里声明了一个block操作
@property (nonatomic, copy) void (^pushBlock) (void);
@end

//点击登录按钮调用block操作
- (IBAction)login:(id)sender {
    [self dismissViewControllerAnimated:YES completion:^{
         self.pushBlock();
     }];
}

第二个:封装数据请求类时候的操作

+ (void)startRegister:(void (^)(BOOL isSuccess, NSMutableArray *finishArray))finishBlock{
         NSString *str = @"登录成功!";
         
         NSMutableArray *array = [[NSMutableArray alloc] init];
         [array addObject:@"1"];
         
         if ([str isEqualToString:@"登录成功!"]){
             // 把yes 或者 no 传递到视图控制器中去使用
             finishBlock(YES,array);
         }else{
             finishBlock(NO,nil);
         }
}

代码请查看 http://git.oschina.net/zcb1603999/LearningiOS

评论已关闭。