注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

尐鬼じ☆ve伱

和你在一起的日子

 
 
 

日志

 
 

使用NSOperation和NSOperationQueue启动多线程开发应用 (转)  

2012-06-12 17:59:12|  分类: ios 开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

http://www.cnblogs.com/lovecode/articles/2275250.html

 Apple从os x10.5在多线程应用的开发上有了很多改进,NSThread的引入使得开发多线程应用程序变得容易多了,尤其是引入了两个全新的类:NSOperation和NSOperationQueue。NSOperation对象类似java.lang.Runnable接口,也被设计为可扩展的,而且只有一个需要重写的方法。这就是-(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];
[super dealloc];
}

- (void)main
{
NSString *webpageString = [[[NSString alloc] initWithContentsOfURL:[self targetURL]] autorelease];
NSError *error = nil;
NSXMLDocument *document = [[NSXMLDocument alloc] initWithXMLString:webpageString options:NSXMLDocuemtTidyHTML error:&error];
if (!document){
NSLog(@"%s Error loading document(%@):%@",_cmd,[[self targetURL] absoluteString], error];
return;
}
[[AppDelegate shared] performSelectorOnMainThread:@selector(pageLoaded:) withObject:document waitUntilDon:YES];
[document release];
}
@end
复制代码

正是这样,该类很简单,只是在其init方法中接受一个url并保存起来,当main函数被调用的时候,它使用这个保存的url创建一个字符串,并将其传递给NSXMLDocumentinit方法。如果加载的xml数据没有出错,数据会被传递给AppDelegate,它处于主线程中。到此,这个线程的任务就宣告完成了。在主线程中注销操作队列时,会将这个NSOperation对象释放。

复制代码
// AppDelegate.h
@interface AppDelegate : NSObject {
NSOperationQueue *queue;
}

+ (id)shared;
- (void)pageLoaded:(NSXMLDocument *)document;
@end

//AppDelegate.m
#import "AppDelegate.h"
#import "PageLoadOperation.h"
@implementation AppDelegate
static AppDelegate *shared;
static NSArray *urlArray;
- (id)init
{
if(shared)
{
[self autorelease];
return shared;
}
if(![super init]) return nil;
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:@"http://www.google.com"];
[array addObject:@"http://www.apple.com"];
[array addObject:@"http://www.yahoo.com"];
[array addObject:@"http://www.zarrastudios.com"];
[array addObject:@"http://www.macosxhints.com"];
urlArray = array;
queue = [[NSOperationQueue alloc] init];
shared = self;
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNatification
{
for(NSString *urlString in urlArray)
{
NSURL *url = [NSURL URLWithString:urlString];
PageLoadOperation *plo = [[PageLoadOperation alloc] initWithURL:url];
[queue addOperation:plo];
[plo release];
}
}

- (void)dealloc
{
[queue release];
[super dealloc];
}

+ (id)shared
{
if(!shared){
[[AppDelegate alloc] init];
}
return shared;
}

- (void)pageLoaded:(NSXMLDocument *)document
{
NSLog(@"%s Do something with the XMLDocuemt:%@",_cmd,document);
}
@end
复制代码

实践问题:在iOS4.0后,如果是并发操作则NSURLConnection无法在NSOperation中正常运行了。即NSURLConnection只能运行于主线程。解决方法可以借鉴以下代码:

复制代码
-(void)download
{
// NSURLConnectionn won't work if it's not in the main thread
if (![NSThread isMainThread])
{
[self performSelectorOnMainThread:@selector(download) withObject:nil waitUntilDone:NO];
return;
}

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:_urlString]];
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
复制代码

这个问题,其实确切是在iOS3中,并发的Operation都是在主线程中执行的,而到了iOS4.0,并发的Operation会在一个独立的线程中执行,这样就产生问题,如果不做特殊的处理,当Operation有异步的调用时,比如NSURLConnection,会由于Operation的start执行之后线程退出了而导致收不到相关的delegate调用。这个问题的标准解决之道是:在NSOperation发出了异步请求之后,启动线程内的runloop。确保线程不退出,同时收到delegate调用。

  评论这张
 
阅读(100)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017