IOS优雅的Block语法

自IOS4.0起加入Block语法,UIKit中超过一百个API使用了Block,主要用在线性遍历(简化代码,更好的抽象),方法回调(相比使用delegate模块化程度更高),异步逻辑(GCD框架下)。

在一些开源的项目里面也都提供支持Block语法的API,如ASIHttpRequest、Reachability等,更有专门扩展现有框架提供Block支持的Blockskit项目。很显然Block对于追求优雅是有很大帮助的。

关于Block实现原理,可以参看:http://blog.csdn.net/jasonblog/article/details/7756763 ,

关于递归和泛型的:http://blog.csdn.net/onlyou930/article/details/6999063,

在此不再累赘说明。

线性遍历

苹果官方例1:没有for循环的代码很美观嘛,Block内部可以使用作用域内的自由变量,申明为__block则会以传引用的方式使用

__block BOOL found = NO;  
NSSet *aSet = [NSSet setWithObjects: @"Alpha", @"Beta", @"Gamma", @"X", nil];  
NSString *string = @"gamma";  

[aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {  
    if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) {  
        *stop = YES;  
        found = YES;  
    }  
}]; 

苹果官方例2:可以看到compareStringsBlock是可以被很好的复用的

NSComperator compareStringsBlock = ^(id stringA, id stringB) {
    NSRange rangeS  = NSMakeRange(0, [stringA length]);
    return (stringA compare:stringB options:comparisonOptions range:rangeS locale:currentLocale];
};
NSArray *compareSortArray  = [arrayOfStringDays sortArrayUsingComparator:compareStringsBlock]);

方法回调

示例1:BlocksKit中对NSTimer的扩展,免去了在另外一个地方写个回调函数的麻烦。

// 启动计时操作
__block int _total = 0;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1 block:^(NSTimeInterval time) {
    _total += 1;
    NSLog(@"total is %d", _total);
    // 这里更新UI界面 显示时间
} repeats:YES];

示例2:ASIHttpRequest中的例子,这里request要申明为__block是防止循环引用

- (IBAction)grabURLInBackground:(id)sender
{
    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
    __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setCompletionBlock:^{
        // Use when fetching text data
        NSString *responseString = [request responseString];

        // Use when fetching binary data
        NSData *responseData = [request responseData];
    }];
    [request setFailedBlock:^{
        NSError *error = [request error];
    }];
    [request startAsynchronous];
}

GCD应用

示例1:方便的创建异步逻辑,并在异步逻辑执行完之后到主线程更新UI

[request setCompletionBlock:^{
    NSData *responseData = [request responseData];
    // 在并发任务队列(非主线程的一个线程池)解包数据并写入数据库
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        UniPacket *uniPacket = [UniPacket fromData:responseData];
        // 此处写入数据库,去除重复数据 并整理要显示的数据_finalDatas
        dispatch_async(dispatch_get_main_queue(), ^{
            // 在此处将finalDatas在主线程中更新到UI界面
        }
    });
}];

作用域问题

因为Block是分配在栈上面的C语言对象,所以要注意其作用域范围,下面的代码block调用是不正确的

同时我们也可以知道,如果要将Block作为函数参数传递的话,或者要异步使用的话,需要先将Block复制为堆上的对象

对于Block里面使用到的上下文对象,Block对象会将其retain一份,使用self访问成员变量和使用成员变量名访问,ratain的对象是不一样的,前者retain的是self,后者retain的是成员变量当前指向的对象

dispatch_block_t block;
if (x) {
    block = ^{ printf("true\n"); };
} else {
    block = ^{ printf("false\n"); };
}
block();

单例模式

既然扯远了,就再扯远点,下面是苹果公司引入的适合创建单例的一种方式

dispatch_once不仅意味着代码仅会被运行一次,而且还是线程安全的,这就意味着你不需要使用诸如@synchronized之类的来防止使用多个线程或者队列时不同步的问题

+ (ClassnName *)sharedInstance 
{
    static ClassnName *obj = nil;
    static dispatch_once_t pred;    
    dispatch_once(&pred, ^{ 
        obj = [[ClassnName alloc] init]; 
    });
    return obj;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值