IOS Block代码块的简单使用

来源:互联网 发布:java云平台搭建 编辑:程序博客网 时间:2024/05/01 21:35
一 代码块的语法

 代码块的书写和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();
原创粉丝点击