多线程和Scroll View
大纲
- 多线程(Multithreading)
将blocks记录到队列(Queues)中(这些blocks将会稍后再其他线程上被执行)
(Vlad_W: 个人理解是你可以把每一个线程看作一个队列)
- UIScrollView
- Demo
- UITableView
多线程
- 队列
多线程在ios中和队列紧密相连。
Blocks被排列在队列中(methods的调用同样可以被加入队列中),然后这些队列中的Blocks会脱离出队列,并且在其他相应线程上执行。
- 主队列(Main Queue)
主队列是一个非常特殊的队列。
所有的界面活动(UI activity)必须也只能出现在这个主队列中。
而且,恰恰相反,所有的非界面活动任何时候都不能出现在主队列中。因为我们希望我们的界面总是可以被响应的。
- 其他队列
大部分的ios会因为需求为我们创建其他队列。
这节课我们大概介绍一下如何创建自己的队列(但是通常我们并不需要这么做)。
- 在另一个队列上执行一个block
<span style="font-size:14px;">dispatch_queue_t queue = ...;
dispatch_async(queue, ^{ });</span>
- 得到主队列
<span style="font-size:14px;">dispatch_queue_t mainQ = dispatch_get_main_queue();
NSOperationQueue *mainQ = [NSOperationQueue mainQueue]; // for object-oriented APIs</span>
- 创建一个队列(非主队列)
<span style="font-size:14px;">dispatch_queue_t otherQ = dispatch_queue_create(“name”, NULL); // name a const char *!</span>
- 简单模型:调用一个主队列上的method
<span style="font-size:14px;">NSObject method ...
- (void)performSelectorOnMainThread:(SEL)aMethod
withObject:(id)obj
<span style="white-space:pre"> </span> waitUntilDone:(BOOL)waitUntilDone; </span>
<span style="font-size:14px;">dispatch_async(dispatch_get_main_queue(), ^{ /* call aMethod */ });</span>
- 例子:使用多线程的IOS API
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL urlWithString:@“http://...”]];
NSURLConfiguration *configuration = ...;
NSURLSession *session = ...;
NSURLSessionDownloadTask *task;
task = [session downloadTaskWithRequest:request
completionHandler:^(NSURL *localfile, NSURLResponse *response, NSError *error) {
/* want to do UI things here, can I? */ }];
[task resume];
<span style="font-size:18px;">downloadTaskWithRequest:<span style="font-family: Arial, Helvetica, sans-serif;">completionHandler:会在非主线程中执行“下载url”的工作。</span></span>
<span style="font-size:18px;"><span style="font-family: Arial, Helvetica, sans-serif;">(如之前所说,因为不是在主线程上执行该工作,所以就算这个工作在等待网络响应的时候,也不会影响UI的正常运作)</span></span>
- 在主队列上
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDownloadTask *task;
task = [session downloadTaskWithRequest:request
completionHandler:^(NSURL *localfile, NSURLResponse *response, NSErr or *error) {
/* yes, can do UI things directly because this is called on the main queue */
}];
[task resume];
因为delegateQueue是主队列,所以completionHandler将会在主队列上。
当URL的下载完成时,上面代码中的block会在主队列上执行。
因此我们可以在这写任何关于UI的代码。
当然,如果你在这里(主队列)做非UI的事情,你最好快一些,避免通过占用主队列而阻碍了UI的响应。
- 不在主队列上
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration]; // no delegateQueue
NSURLSessionDownloadTask *task;
task = [session downloadTaskWithRequest:request
completionHandler:^(NSURL *localfile, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{ /* do UI things */ });
or [self performSelectorOnMainThread:@selector(doUIthings) withObject:nil waitUntilDone:NO];
}];
[task resume];
在以上例子中,你不能做任何和UI相关的事情,因为completionHandler不在主队列上。
如果你想要做UI相关的事情,你必须将一个block或者method添加回主队列上。