本文来源地址:http://www.osjoin.com
block块语法和c中的函数指针类似。
函数的定义是一样的,但是,函数名就换成了(*p)
回顾一下 c的函数指针用法
//函数的指针精髓在?回调
//int(*ps)(int,int) = sum;
//NSLog(@"%d",ps(3,6));
在此处创建了一个函数指针
1:block的创建
// int (^blo)(int a,int b) = ^(int a,int b) // { // return a+ b; // };
在等号右边的 ^ 后面可以数据类型,即返回类型,但是在oc中这块系统会识别返回的数据类型。当然如果不返回数据,就不考虑返回值了。
2:调用
上面的block调用的时候,和函数指针调用类似。
int nums = blo(1,2);
NSLog(@"%d",nums);
调用完之后,打印一下数据。即可得到对应的数据。
在来一个列子看看:利用块语法实现把“123”转换成123。
// int (^bloc)(NSString *nums) = ^(NSString *nums)
// {
// return [nums intValue];
// };
//1.编程实现:
实现一个block完成一个功能,第一个参数是一个数组,第二个参数是一个int类型变量,遍历数据,查看数据中是否存在这个数,如果存在返回下标,如果不存在返回-1。
下面是实现和调用
int (^funcArry)(int a[5],int b) = ^(int a[5],int b)
{
int falg = -1;
for (int index = 0; index < 5; index++) {
if (a[index] == b) {
return falg = index;
break;
}else
{
continue;
}
}
return falg;
};
int ac[] = {1,2,3,4,5,6};
int str = funcArry(ac,9);
//定义一个局部变量
__block int count = 0;
//在block块里对局部变量访问,并且修改值,返回修改之后的值
int (^blo)(int a) = ^(int a)
{
count = count + a;
return count;
};
注意:在使用局部变量时,系统会提示一个错误。
-------解决办法就是在使用的局部变量时,在局部的变量前加 __block,在block前加两个下划线。
在使用全局变量时和普通变量一样的使用,好像没什么特别之处。
5:实际应用场景
1:有一个student类,属性全部为@public
//code。。。
处理之后会得到一个可变的数组。(也可以不是可变的数组)
NSMutableArray *arrys = [[NSMutableArray alloc] initWithObjects:stu,stu1,stu2,stu3,stu4, nil];
[arrys sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
//将上面的obj强制转换为studnent
Student *curr = (Student *)obj1;
Student *next = (Student *)obj2;
//按年龄比较
if (curr->_age < next->_age) {
//返回值表示的是,要不要进行元素的交换
return YES;
}
else
{
return NO;
}
}];
在这里就用到了实际块语法,具体的解释没一行都有解释。
当然在不可变的数组中用到的排序方法为:
NSArray *resu = [arry sortedArrayUsingComparator:^NSComparisonResult(id obj1,id obj2) {};
6:在排序完之后打印的方法
因为每个数据类型都是student的,所以在便利的时候用 student *stu
for (Student *stuin arrys) {
NSLog(@"%@++++++++++%ld",stu->_name,stu->_age);
}
事咧代码下载地址:http://download.csdn.net/detail/whuizhou/8862861
Block确实是个好东西, 但是用起来一定要注意循环引用的问题, 否则一不小心你就会发现, Oh My God, 我的dealloc肿木不走了...
__weak typeof(self) weakSelf = self;
dispatch_block_t block = ^{
[weakSelf doSomething]; // weakSelf != nil
// preemption, weakSelf turned nil
[weakSelf doSomethingElse]; // weakSelf == nil
};
如此在上面定义一个weakSelf, 然后在block体里面使用该weakSelf就可以避免循环引用的问题. 那么问题来了...是不是这样就完全木有问题了? 很不幸, 答案是NO, 还是有问题。问题是block体里面的self是weak的, 所以就有可能在某一个时段self已经被释放了, 这时block体里面再使用self那就是nil, 然后...然后就悲剧了...那么肿么办呢?
__weak typeof(self) weakSelf = self;
myObj.myBlock = ^{
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomething]; // strongSelf != nil
// preemption, strongSelf still not nil
[strongSelf doSomethingElse]; // strongSelf != nil
}
else {
// Probably nothing...
return;
}
};
解决方法很简单, 就是在block体内define一个strong的self, 然后执行的时候判断下self是否还在, 如果在就继续执行下面的操作, 否则return或抛出异常.
什么情况下会出现block里面self循环引用的问题? 这个问题问的好, 哈哈...简单来说就是双边引用, 如果block是self类的property (此时self已经retain了block), 然后在block内又引用了self, 这个情况下就肯定会循环引用了...
P.S. RAC里面有定义好的@weakify(self)和@strongify(self), 用起来灰常灰常的方便, 劝君尝试一下^_^
也可以添加洲洲哥的微信公众号
更多信iOS开发信息 请以关注洲洲哥 的微信公众号,不定期有干货推送: