IOS编程中使用多线程
在app store中的很多应用程序非常的笨重,他们有好的界面,但操作性很差,比如说当程序从网上或本地载入数据的时候,界面被冻结了,用户只能等程序完全载入数据之后才能进行操作。 当打开一个应用程序时,iphone会产生一个包含main方法的线程,所用程序中的界面都是运行在这个线程之中的(table views, tab bars, alerts…),有时候我们会用数据填充这些view,现在问 题是如何有效的载入数据,并且用户还能自如的操作程序。方法是启动新的线程,专门用于数据的下载,而主线程不会因为下载数据被阻塞。 不管使用任何编程语言,在实现多线程时都是一件很麻烦的事情。更糟糕的是,一旦出错,这种错误通常相当糟糕。然而,幸运的是apple从os x10.5在这方面做了很多的改进,NSThread的引入,使得开发多线程应用程序容易多了。除此之外,它们还引入了两个全新的类,NSOperation和NSOperationQueue。 ### IOS编程中使用多线程 #### 背景与问题描述 在iOS应用开发过程中,经常遇到的一个问题是:应用程序加载数据时导致UI界面卡顿甚至假死,从而严重影响用户体验。例如,当从网络或者本地数据库加载大量数据时,由于主程序线程被长时间占用,用户界面将无法响应用户的任何交互动作,直到数据加载完成。这不仅降低了应用程序的响应速度,而且可能会让用户感到困惑和不耐烦。 #### 解决方案——多线程技术的应用 为了改善这一状况,可以采用多线程技术来处理数据加载等耗时操作,确保用户界面始终保持活跃状态。苹果公司在OS X 10.5及后续版本中,对多线程的支持进行了显著增强,引入了`NSThread`、`NSOperation`以及`NSOperationQueue`等类,使得开发者能够更加轻松地管理和控制多线程任务。 #### NSThread简介 `NSThread`是Objective-C中用于创建和管理线程的基本类。它允许开发者定义和执行独立于主线程的任务。使用`NSThread`创建新线程的基本步骤如下: 1. 创建一个新的`NSThread`实例。 2. 定义线程的执行逻辑(通常是通过实现`main`方法)。 3. 调用`start`方法启动线程。 然而,直接使用`NSThread`管理多个并发任务较为繁琐,特别是当涉及到线程同步和依赖关系时。为了解决这个问题,苹果公司提供了更高级别的抽象——`NSOperation`和`NSOperationQueue`。 #### NSOperation与NSOperationQueue `NSOperation`是另一种执行后台任务的方式,相比于`NSThread`更为灵活和强大。它不仅可以封装任意的任务逻辑,还可以与其他`NSOperation`对象之间建立依赖关系,从而实现复杂的并发任务调度。 - **NSOperation**:每个`NSOperation`对象代表一个具体的任务,内部封装了任务的执行逻辑。可以通过重写`main`方法来定义具体的任务逻辑。 - **NSOperationQueue**:用于管理一系列`NSOperation`对象的队列。它可以自动调度队列中的任务,支持设置最大并发数等高级功能。 #### 实战示例 下面是一个简单的示例代码,展示了如何使用`NSOperation`和`NSOperationQueue`来异步加载网页数据,并在主线程中更新UI。 1. **定义NSOperation子类**:首先需要创建一个自定义的`NSOperation`子类,用于封装网页加载的具体逻辑。 ```objective-c @interface PageLoadOperation : NSOperation @property (nonatomic, retain) NSURL *targetURL; - (id)initWithURL:(NSURL *)url; @end @implementation PageLoadOperation - (id)initWithURL:(NSURL *)url { if (![super init]) return nil; self.targetURL = [url retain]; return self; } - (void)main { NSString *webpageString = [[NSString alloc] initWithContentsOfURL:self.targetURL encoding:NSUTF8StringEncoding error:nil]; NSError *error = nil; NSXMLDocument *document = [[NSXMLDocument alloc] initWithXMLString:webpageString options:NSXMLDocumentTidyHTML error:&error]; if (!document) { NSLog(@"Error loading document (%@): %@", self.targetURL, error); return; } [[AppDelegate shared] performSelectorOnMainThread:@selector(pageLoaded:) withObject:document waitUntilDone:YES]; [document release]; } @end ``` 2. **AppDelegate类**:接下来,我们需要在`AppDelegate`类中定义一个`NSOperationQueue`实例,并实现一个更新UI的方法。 ```objective-c @interface AppDelegate : NSObject @property (nonatomic, strong) NSOperationQueue *queue; + (instancetype)shared; - (void)pageLoaded:(NSXMLDocument *)document; @end @implementation AppDelegate + (instancetype)shared { static AppDelegate *shared = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ shared = [[AppDelegate alloc] init]; }); return shared; } - (instancetype)init { self = [super init]; if (self) { self.queue = [[NSOperationQueue alloc] init]; } return self; } - (void)pageLoaded:(NSXMLDocument *)document { // 在这里更新UI } @end ``` 3. **使用NSOperationQueue**:可以在适当的地方创建并添加`PageLoadOperation`到`NSOperationQueue`中。 ```objective-c NSURL *url = [NSURL URLWithString:@"http://example.com"]; PageLoadOperation *operation = [[PageLoadOperation alloc] initWithURL:url]; [AppDelegate.shared.queue addOperation:operation]; ``` 通过上述步骤,我们成功地实现了异步网页加载并更新UI的功能,避免了因数据加载而导致的UI卡顿问题。这种方式不仅提高了应用的性能和响应速度,也大大提升了用户体验。
在app store中的很多应用程序非常的笨重,他们有好的界面,但操作性很差,比如说当程序从网上或本地载入数据的时候,界面被冻结了,用户只能等程序完全载入数据之后才能进行操作。
当打开一个应用程序时,iphone会产生一个包含main方法的线程,所用程序中的界面都是运行在这个线程之中的(table views, tab bars, alerts…),有时候我们会用数据填充这些view,现在问 题是如何有效的载入数据,并且用户还能自如的操作程序。方法是启动新的线程,专门用于数据的下载,而主线程不会因为下载数据被阻塞。
不管使用任何编程语言,在实现多线程时都是一件很麻烦的事情。更糟糕的是,一旦出错,这种错误通常相当糟糕。然而,幸运的是apple从os x10.5在这方面做了很多的改进,NSThread的引入,使得开发多线程应用程序容易多了。除此之外,它们还引入了两个全新的类,NSOperation和NSOperationQueue。
接下来我们通过一个实例来剖析如何使用这两个类实现多线程。这里指示展示这两个类的基本用法,当然这不是使用他们的唯一办法。
如果你熟悉java或者它的别的变种语言的话 ,你会发现NSOperation对象很像java.lang.Runnable接口,就像java.lang.Runnable接口那样,NSOperation类也被设计为可扩展的,而且只有一个需要重写的方法。它就是-(void)main。使用NSOperation的最简单的方式就是把一个NSOperation对象加入到NSOperationQueue队列中,一旦这个对象被加入到队列,队列就开始处理这个对象,直到这个对象的所有操作完成。然后它被队列释放。
下面的例子中,使用一个获取网页,并对其解析程NSXMLDocument,最后将解析得到的NSXMLDocument返回给主线程。
PageLoadOperation.h@interface PageLoadOperation : NSOperation {
NSURL *targetURL;}
@property(retain) NSURL *targetURL;
- (id)initWithURL:(NSURL*)url;@end
PageLoadOperation.m
#import "PageLoadOperation.h"#import "AppDelegate.h"@implementation PageLoadOperation@synthesize targetURL;- (id)initWithURL:(NSURL*)url;{
if (![super init]) return nil;
[self setTargetURL:url];
return self;}- (void)dealloc {
[targetURL release], targetURL = nil;
[super dealloc];
}
- (void)main
{
NSString *webpageString = [[[NSString alloc]
initWithContentsOfURL:[self targetURL]] autorelease];
NSError *error = nil;
NSXMLDocument *document = [[NSXMLDocument alloc]
initWithXMLString:webpageString
options:NSXMLDocumentTidyHTML error:&error];
if (!document) {
- zhangke94122012-08-13不错,如果是个demo就更好了
- zhang7402011-09-10代码不错~方法挺好用。不过就一个txt啊。。。
- wangxiaobu2011-12-27还好,就是不能直接用。
- Rainbow_Me2011-10-25挺有用的,代码不错,编译能通过
- luyi08240732013-06-24非常好的资源,谢谢楼主分享
- 粉丝: 5
- 资源: 9
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (源码)基于Java和MySQL的学生信息管理系统.zip
- (源码)基于ASP.NET Core的零售供应链管理系统.zip
- (源码)基于PythonSpleeter的戏曲音频处理系统.zip
- (源码)基于Spring Boot的监控与日志管理系统.zip
- (源码)基于C++的Unix V6++二级文件系统.zip
- (源码)基于Spring Boot和JPA的皮皮虾图片收集系统.zip
- (源码)基于Arduino和Python的实时歌曲信息液晶显示屏展示系统.zip
- (源码)基于C++和C混合模式的操作系统开发项目.zip
- (源码)基于Arduino的全球天气监控系统.zip
- OpenCVForUnity2.6.0.unitypackage