发一条动态
在很多UGC产品中(如微博、赤兔、朋友圈),发一条图文并茂的动态总是群众喜闻乐见的。如下图:
根据产品流程,我们应该会有一个表示动态的数据结构,其中包括了文字属性和多个图片的url。伪代码如下:
class feed {
string text;
string[] imageURLs;
}
发布图片的流程如下:
先将这多张图上传到服务器并返回图片对应的url,然后再把这些图片url和文字作为动态的属性发布到服务器。今天要讨论的就是如何利用GCD来提高效率。
小明的代码
耗时的UI操作使用多线程可以有效提高性能,在iOS开发中,多线程的实现主要靠gcd和NSOperation,各有优劣和使用场景,这不是此文的重点。
分析上述方案,可以得知有一个约束:必须所有的图片都上传成功以后再发布动态。
小明可能这样写:
sendPhoto(image1, success:^(NSString *url){
sendPhoto(image2, success:^(NSString *url) {
sendPhoto(image3, success:^(NSString *url) {
.......
postFeed(imageURLs, text);
});
});
});
这只是一个反面例子,它不好是因为:
- 任务是串行执行的,效率低下。在这种场景下发布一条动态耗时可能会很长,体验很差。
- 实现丑陋。看看上面的代码片段中有多少个
});
吧
小红的代码
其实多图的发布可以并发操作,dispatch_group大显身手的时候到了。苹果官方文档是是这样描述的:
Grouping blocks allows for aggregate synchronization. Your application can submit multiple blocks and track when they all complete, even though they might run on different queues. This behavior can be helpful when progress can’t be made until all of the specified tasks are complete.
dispatch_group提供了多个block之间的同步机制,可以在多个block都执行完成之后,再执行有依赖的任务。
于是,小红改了代码:
NSMutableArray *imageURLs= [NSMutableArray array];
dispatch_group_t group = dispatch_group_create(); // 1
for (UIImage *image in images) {
dispatch_group_enter(group); // 2
sendPhoto(image, success:^(NSString *url) {
[imageURLs addObject:url];
dispatch_group_leave(group); // 3
});
}
dispatch_group_notify(group, dispatch_get_global_queue(), ^{ // 4
postFeed(imageURLs, text);
});
- 首先创建一个dispatch_group
-
dispatch_group_enter
往group中增加一个block任务,dispatch_group_leave
则表示该block已经执行完成。需要注意的是,enter和leave必须配对。在这个例子当中,每一个block任务就是上传一张图片。
Calling this function increments the current count of outstanding tasks in the group. Using this function (withdispatch_group_leave
) allows your application to properly manage the task reference count if it explicitly adds and removes tasks from the group by a means other than using the dispatch_group_async
function. A call to this function must be balanced with a call to dispatch_group_leave
. You can use this function to associate a block with more than one group at the same time.
- 当group中之前所有提交的block任务都执行完后,
dispatch_group_notify
中的block任务就会被执行。在此例中,所有的图片都上传成功之后,就会发布动态。
总结
对比小明和小红的代码,小明的模型是这样的:
小红的是这样的:
使用dispatch group,我们可以很轻松并高效地处理任务依赖。