介绍一下iPhone SDK中多线程的使用方法以及注意事项。虽然现在大部分PC应用程序都支持多线程/多任务的开发方式,但是在iPhone上,Apple并不推荐使用多线程的编程方式。但是多线程编程毕竟是发展的趋势,而且据说即将推出的iPhone OS4将全面支持多线程的处理方式。所以说掌握多线程的编程方式,在某些场合一定能挖掘出iPhone的更大潜力。 多线程程序的控制模型可以参考这里,一般情况下都是使用 管理者/工人模型, 这里,我们使用iPhone SDK中的NSThread 来实现它。 首先创建一个新的View-based application 工程,名字为"TutorialProject" 。界面如下图所示,使用UILabel实现两部分的Part(Thread Part和Test Part),Thread Part中包含一个UIProgressView和一个UIButton;而Test Part包含一个值和一个UISlider。 在TutorialProjectViewController.h 文件中创建各个UI控件的IBOutlets. @interface TutorialProjectViewController : UIViewController { // ------ Tutorial code starts here ------ // Thread part IBOutlet UILabel *threadValueLabel; IBOutlet UIProgressView *threadProgressView; IBOutlet UIButton *threadStartButton; // Test part IBOutlet UILabel *testValueLabel; // ------ Tutorial code ends here ------ } 同时,也需要创建outlets变量的property. @property (nonatomic, retain) IBOutlet UILabel *threadValueLabel; @property (nonatomic, retain) IBOutlet UIProgressView *threadProgressView; @property (nonatomic, retain) IBOutlet UIProgressView *threadStartButton; @property (nonatomic, retain) IBOutlet UILabel *testValueLabel; 接下来定义按钮按下时的动作函数,以及slider的变化函数。 - (IBAction) startThreadButtonPressed:(UIButton *)sender; - (IBAction) testValueSliderChanged:(UISlider *)sender; 然后在TutorialProjectViewController.m 文件中synthesize outlets,并在文件为实现dealloc释放资源。 @synthesize threadValueLabel, threadProgressView, testValueLabel, threadStartButton; ... - (void)dealloc { // ------ Tutorial code starts here ------ [threadValueLabel release]; [threadProgressView release]; [threadStartButton release]; [testValueLabel release]; // ------ Tutorial code ends here ------ [super dealloc]; } 现在开始线程部分的代码,首先当thread button 被按下的时候,创建新的线程. - (IBAction) startThreadButtonPressed:(UIButton *)sender { threadStartButton.hidden = YES; threadValueLabel.text = @"0"; threadProgressView.progress = 0.0; [NSThread detachNewThreadSelector:@selector(startTheBackgroundJob) toTarget:self withObject:nil]; } 该按钮被按下后,隐藏按钮以禁止多次创建线程。然后初始化显示值和进度条,最后创建新的线程,线程的函数为startTheBackgroundJob. 具体的startTheBackgroundJob 函数定义如下. - (void)startTheBackgroundJob { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // 线程开始后先暂停3秒(这里只是演示暂停的方法,你不是必须这么做的) [NSThread sleepForTimeInterval:3]; [self performSelectorOnMainThread:@selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO]; [pool release]; } 在第1行,创建了一个NSAutoreleasePool 对象,用来管理线程中自动释放的对象资源。这里NSAutoreleasePool 在线程退出的时候释放。这符合Cocoa GUI 应用程序的一般规则。 最后一行,阻塞调用(waitUntilDone状态是ON)函数makeMyProgressBarMoving。 - (void)makeMyProgressBarMoving { float actual = [threadProgressView progress]; threadValueLabel.text = [NSString stringWithFormat:@"%.2f", actual]; if (actual < 1) { threadProgressView.progress = actual + 0.01; [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(makeMyProgressBarMoving) userInfo:nil repeats:NO]; |