GCD异步访问URL的宏

目的

平时在框架里面用来调用服务端接口的都是使用第三方的网络框架,比如ASIHttpRequest和AFNetworking等,又或者自己在这基础上封装的一套工具。但异步操作的代码写起来有时也觉得不够优雅。

用GCD能很方便使用多线程之后,我也在想看看能否用更轻量级、更优雅点的做法取代。

下面是用简单的做法来尝试,即访问URL都是直接同步获取,但是这种操作每次都开一个线程来做。比如:

- (void)runWithUrl:(NSString*)url
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self.activeView startAnimating];
        NSString *html =[self getHTMLStringWithUrl:url];
        html = [html substringToIndex:240];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [self showWithString:html];
            [self.activeView stopAnimating];
        });
        
    });
}

- (id)getHTMLStringWithUrl:(NSString*)url
{
    NSURL *URL = [NSURL URLWithString:url];
    NSError *erorr;
    NSString *result = [NSString stringWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&erorr];
    return result;
}

也算简洁,但是如果每次都这么写也是挺烦人的,而且多重嵌套的block光阅读也累人,谈不上优雅。

所以我用点小技巧,改用宏定义来简化。

宏定义

#define ASYNC_START  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
#define ASYNC_DONE   dispatch_async(dispatch_get_main_queue(), ^{
#define ASYNC_END   }); });

简化写法

所以上述的代码被修改为这样:

- (void)runAsyncWithUrl:(NSString*)url
{
    ASYNC_START
        [self.activeView startAnimating];
        NSString *html =[self getHTMLStringWithUrl:url];
        html = [html substringToIndex:240];
    
    ASYNC_DONE
        [self showWithString:html];
        [self.activeView stopAnimating];
    
    ASYNC_END
}
...

不用写一长串dispatch了,而且看起来不像异步操作,而像同步获取到数据,然后顺序执行本该写在回调函数里的内容一般。看起来清爽多了。

但这也就是业余时候玩一玩而已,不敢用在生产环境里。不过以后再完善一下,增加其他诸如处理错误的宏,封装成一套工具,说不定会变得很实用。