IOS Block代码块的简单使用

本文深入探讨了Objective-C代码块的语法、调用方式、变量访问及使用场景,详细介绍了如何在函数间传递代码块作为参数,并讨论了代码块内部变量的访问规则,特别强调了独立代码块与内联代码块的区别。通过实例演示,读者能够掌握代码块在回调函数、代理方法替代等场景中的高效应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码块的语法


 代码块的书写和C语言函数的语法格式有点像,例如下面求和函数分别用C 语言和代码块来实现:


int add(int a,int b)

{

     return a+b;

}


int (^add)(int a,int b) = ^(int a,int b)

{

    return a +b;

};


注意:a.代码块最后的大括号后面一定要加分号。

          b.c语言的函数签名不同的是,代码块的名字需要用'^'和括号。

          c. 代码块的签名部分和实现部分需要用'^(参数列表)'来连接。


除次之外代码块还可以将签名和实现部分分开来实现,例如:

void (^PrintInfo)(NSString *info);

   

PrintInfo = ^(NSString *info)

{

   NSLog(@"%@",info);

};


 代码块也可以看作是函数的指针,差别是用^代替了*.


代码块的调用方式

1.直接调用,例如,对于刚才定义的PrintInfo代码块


  PrintInfo(@"Hello World");

      


2.使用代码块"指针"的方式来实现,例如:

 

 typedef void (^Print) (NSString *info);

 

 void (^PrintName) (NSString * name) = ^(NSString * name)

 {

    NSLog(@"MyName:%@",name);

 };


 Print myBlock = PrintName;

 myBlock(@"Hello");



 void (^PrintCountry)(NSString * Country)= ^(NSString *Country)

 {

     NSLog(@"MyCountry:%@",Country);

 };

 myBlock= PrintCountry;

 myBlock(@"China");

  

: 在一个block的内部可以调用另外一个block

  /*************** Definition of first block object ***************/ 

NSString *(^trimString)(NSString *) = ^(NSString *inputString)

{

     NSString *result = [inputString stringByTrimmingCharactersInSet

                                          [NSCharacterSet whitespaceCharacterSet]];

     return result;

};

/*************** Definition of second block object ***************/ 

NSString *(^trimWithOtherBlock)(NSString *) = ^(NSString *inputString)

{

    return trimString(inputString);

}

3.使用方法举例

       

       代码块的作用主要是用来做回调函数来使用的,它可以代替IOS SDK中的代理方法。使用代码块比用代理

方法的效率更高。


a.首先定义两个代码块指针

typedef void (^SucceedBlock)(void); //访问服务器成功的时候

typedef void (^FailedBlock )(void); //访问服务器失败的时候


b.定义访问服务器方法

- (void) getDataFromServer:(NSString*) URL succeedBlock:(SucceedBlock) succeed 

                                            failedBlock:(FailedBlock) fail

{

    //模拟调用成功和失败

    if ([URL isEqualToString:@"YES"])

    {

        succeed();

    }

    else

    {

        fail();

    }

}

c.调用上面的方法


void (^succeedBlock)(void) = ^

{

    NSLog(@"do something succeed thing");

};


void (^failedBlock)(void) = ^

{

    NSLog(@"do some failed thing");

};


采用独立代码块的方式实现函数的调用

[self getDataFromServer:@"YES" succeedBlock:succeedBlock failedBlock:failedBlock];


也可以在调用的时候来定义代码块(内联的方式实现代码块的调用)

[self getDataFromServer:@"NO" succeedBlock:^{

        NSLog(@"inline succeed block!");

    }failedBlock:^{

        NSLog(@"inline failed block!");

    }

];

d.直接用代码块作参数

-(void) testBlock:(NSString*)name completionBlock:(void (^)(NSString* addr)) block

{

    block(name);

}

[self testBlock:@"zhangzhe" completionBlock:^(NSString *addr)

{

     NSLog(@"addr:%@",addr);

}];

代码块中变量访问

a.对于独立代码块,内部定义的局部变量的使用方式和普通的objective-c函数是相同的,可以进行读写

      void (^independentBlockObject)(void) = ^(void)

    {

        NSInteger localInteger = 10;

        NSLog(@"local integer = %ld", (long)localInteger);

        lojalitetger = 20;

        NSLog(@"local integer = %ld", (long)localInteger);

    };

localInteger是可以被读写的

b.对于内联方式定义的代码块,局部变量不仅包括在代码块内部定义的变量,而且还包含在实现代码块

   函数内部定义的变量。对于前一部分变量是可读写的,对于后一部分变量是只读的。例如:

- (void)viewDidLoad

{

    int outsideInteger = 10;

    [self getDataFromServer:@"NO" succeedBlock:^{

        int insideInteger = 10;

        ++insideInteger;

        //outsideInteger = 5; //这样直接写会报错误 提示outsideInteger没有加__block

        NSLog(@"ousideInteger=%d  insideInteger=%d",outsideInteger,insideInteger);

    }failedBlock:^{

        NSLog(@"inline failed block!");

    }];

}

所以对于代码块外定义的局部变量是只读的,要想可以读写需要在改变量前面加两个下划线+block  

    __block  int outsideInteger = 10;

c.对于selfl变量的访问,如果是在独立代码块不能直接访问self变量,要访问可以将其作为代码块参数传入,对于内联点名块,只要在实现该代码块的函数可以访问的话,在代码块内部就可以直接访问。

void (^correctBlockObject)(id) = ^(id self)

{

     NSLog(@"self = %@", self);

};

- (void)viewDidLoad

{

    [self getDataFromServer:@"NO" succeedBlock:^{

        NSlog(@"self = %@",self);

    }failedBlock:^{

        NSLog(@"inline failed block!");

    }];

}

d.对于使用 @property定义的属性变量的访问,如果内联代码块可以使用点号的方式访问,也可以使用

  方括号的方式来访问,但是对于独立代码块的话只能使用后者来访问。


 @interface GASSViewController : UIViewController

  @property(nonatomic,strongNSString *name;

 @end


对于独立代码块

 void (^correctBlockObject)(id) = ^(id self)

 {

    NSLog(@"self = %@", self);

    /* Should use setter method instead of this */

    self.name = @"Block Objects"; /* Compile-time Error */

    /* Should use getter method instead of this */

     NSLog(@"self.name = %@",self.name); /* Compile-time Error */

 };

对于内联代码块

[self getDataFromServer:@"NO" succeedBlock:^{

        NSLog(@"self.name = %@",self.name);

    }failedBlock:^{

        NSLog(@"inline failed block!");

}];

e.对于代码块外的变量,代码块会拷贝到自己的一个结构体内(相当于深拷贝),需要注意的是这个深拷贝是在定义代码块的时候进行的,而不是你调用的时候。

  typedef void (^BlockWithNoParams)(void); 

   - (void) scopeTest  

   {

        NSUInteger integerValue = 10;

        /*************** Definition of internal block object ***************/ 

        BlockWithNoParams myBlock = ^{

            NSLog(@"Integer value inside the block = %lu", (unsigned long)integerValue);

        };

        /*************** End definition of internal block object ***************/

        integerValue = 20;

        /* Call the block here after changing the value of the integerValue variable */

        myBlock();

        NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue);

    }

   输出的结果:

      Integer value inside the block  = 10 

     Integer value outside the block = 20


避免这种情况

   - (void) scopeTest  

   {

         __block NSUInteger integerValue = 10;

        /*************** Definition of internal block object ***************/ 

        BlockWithNoParams myBlock = ^{

            NSLog(@"Integer value inside the block = %lu", (unsigned long)integerValue);

        };

        /*************** End definition of internal block object ***************/

        integerValue = 20;

        /* Call the block here after changing the value of the integerValue variable */

        myBlock();

        NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue);

    }

   输出的结果:

     Integer value inside the block  = 20 

     Integer value outside the block = 20


d.对于类中的实例成员来说,在代码块中可以直接访问是可以读写的,不用写__block

  @interface GASSViewController ()

  @property(nonatomic,strong) NSArray *testArr;

 @end


   @implementation GASSViewController

  @synthesize testArr = _testArr;


  void (^independentBlockObject)(void) = ^(void)

  {

     self.testArr = @[@"ONE",@"TWO"];

  };

  independentBlockObject();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值