有些时候我们需要进行处理大量数据或其他非常耗时的操作,为了不影响程序对用户的响应,我们必须将这些事情放在一个新线程里进行。这样可以与主线程(UI线程)分开,当任务完成后,在返回主线程处理。android平台下我们可以通过handler和message来实现上述功能。那么ios平台下是如何做的呢?接下我们通过一个下载网络图片的小例子进行学习。
新建一个项目命名为ThreadApp。向ViewController.xib拖入一个UIImageView控件和UIActivityIndicatorView控件如图:
打开ViewController.h文件添加如下代码:
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *indicator;
- (void)loadingPicture:(id)sender;
- (void)loadingpictureDone:(NSData *)data;
我们定义了两个输出口,一个是用来显示下载的图片一个是用来更新进度条(小菊花)的。
另外我们定义了两个函数- (void)loadingPicture:(id)sender用来下载图片,另外一个- (void)loadingpictureDone:(NSData *)data当下载完成后显示图片并关闭小菊花。
修改ViewController.m文件如下:
#import "ViewController.h"
@implementation ViewController
@synthesize imageView;
@synthesize indicator;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)loadingPicture:(id)sender
{
NSString *url = [NSString stringWithFormat:@"http://img.xiami.com/images/collect_pic/64/71/3235848/1334149254_NmHG.jpg"];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
[url release];
NSLog(@"Thread is running...");
[self performSelectorOnMainThread:@selector(loadingpictureDone:) withObject:data waitUntilDone:YES];
}
- (void)loadingpictureDone:(NSData *)data
{
UIImage *image = [UIImage imageWithData:data];
if (image) {
self.imageView.image = image;
[self.indicator stopAnimating];
self.indicator.hidden = YES;
NSLog(@"loading picture done.");
}
[image release];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = @"Loading Picture";
[self.indicator startAnimating];
[NSThread detachNewThreadSelector:@selector(loadingPicture:) toTarget:self withObject:nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.indicator = nil;
self.imageView = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)dealloc{
[self.indicator release];
[self.imageView release];
[super dealloc];
}
@end
在viewDidLoad函数中我们启动一个新线程并开启小菊花动画
[self.indicator startAnimating]; //启动进度条动画
[NSThread detachNewThreadSelector:@selector(loadingPicture:) toTarget:self withObject:nil]; //开启一个新线程下载图片
ios下启动一个新线程方法:
[NSThread detachNewThreadSelector:@selector(loadingPicture:) toTarget:self withObject:nil];
方法loadingPicture为我们要在新线程中做的事,在loadingPicture中
[self performSelectorOnMainThread:@selector(loadingpictureDone:) withObject:data waitUntilDone:YES];
上述代码实现了当下载完成后我们要做的事,我们又回到主线程处理相关数据。我们使用loadingPictureDone方法来处理下载完成后的事情。
这里我们更新图片,并隐藏小菊花
UIImage *image = [UIImage imageWithData:data];
if (image) {
self.imageView.image = image;
[self.indicator stopAnimating];
self.indicator.hidden = YES;
NSLog(@"loading picture done.");
}
[image release];
效果图:
这里我只是下载一个图片作为演示。
总结:在ios下启动一个线程过程大致如下:当我们将要处理比较耗时的任务时,我们在合适的地方使用 [NSThread detachNewThreadSelector:@selector() toTarget:target withObject:obh]方法来开启一个新线程来处理任务,在任务完成时,调用[self performSelectorOnMainThread:@selector() withObject:obj waitUntilDone:YES]方法来更新UI或执行其他操作!
好了就写这么多,有什么问题请留言,大家一起学习交流!
说明:转载请注明出处!