大家都明白,创建线程的目的就是让程序同时做多件事情,尤其是对于需要长时间执行的操作,让用户等着他完成是不科学的。一般处理模式是,与用户息息相关的界面显示使用主线程,与界面相关的信息处理及逻辑处理我们会开启另外一个线程处理,这样不妨碍用户与界面的互动。
本篇使用NSThread创建线程,来封装一个需要长时间的操作,处理完后再通知主线程刷新界面。
可以直接使用NSThread创建线程,不过这样会将所有代码放置再主线程中,耦合的有点厉害,我建议派生NSThread,将长时间操作放在派生类的main函数中。本例main函数中先睡眠10秒,再获取一张图片,完成后通知主线程。
//
// MyThread.h
//
#import <Foundation/Foundation.h>
#import "MQLOtherViewController.h"
@interface MyThread : NSThread
@property(nonatomic, weak) MQLOtherViewController *delegate;
@end
//
// MyThread.m
//
#define kURL @"http://avatar.csdn.net/6/0/2/3_qianlima210210.jpg"
#import "MyThread.h"
@implementation MyThread
-(void)main
{
[self downloadImage:kURL];
}
-(void)downloadImage:(NSString *) url{
NSLog(@"downloadImage = %@", self);
sleep(10);
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
if ([self isCancelled]) {
[NSThread exit];
return;
}
UIImage *image = [[UIImage alloc]initWithData:data];
if(image == nil){
}else{
[self.delegate performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:NO];
}
}
@end
封装完后,我们在主线程中使用封装好的线程类:
//
// MQLOtherViewController.h
//
#import <UIKit/UIKit.h>
@interface MQLOtherViewController : UIViewController
-(void)updateUI:(UIImage*) image;
@end
//
// MQLOtherViewController.m
//
#import "MQLOtherViewController.h"
#import "MyThread.h"
@interface MQLOtherViewController ()
@property (nonatomic, strong) MyThread *thread;
@property (nonatomic, weak) IBOutlet UIImageView *imageview;
-(IBAction)startClicked:(id)sender; //启动按钮的响应函数
-(IBAction)cancelClicked:(id)sender; //取消按钮的响应函数
@end
@implementation MQLOtherViewController
-(IBAction)startClicked:(id)sender
{
self.thread = [[MyThread alloc]init];//创建子线程
self.thread.delegate = self; //设置子线程的代理
[self.thread start]; //启动子线程,start中会调用main函数,所以我将长时间操作放在了main里
}
-(IBAction)cancelClicked:(id)sender
{
[self.thread cancel]; //取消线程,cancel并没有中止子线程,仅仅设置了取消状态,子线程应使用isCancelled判断来使用exit中止子线程
}
-(void)updateUI:(UIImage*) image{
NSLog(@"updateUI");
self.imageview.image = image;
}
@end