原文地址http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/

在任何一种语言里,线程都是一个难点,更糟糕的是,如果线程出了问题,往往会以一种非常糟糕的方式出现。因为这个,程序员要么竭力避免线程编程(将线程看作是魔鬼的种子),要么花费大量时间去确保所有线程代码都运行良好。

幸运的是,Apple在OS X 10.5 leopard 有了很大的进步。NSThread类添加了很多非常有用的新方法,这些方法都使线程编程变得更加简单。另外,Apple引入了两个新的对象:NSOperation和NSOperationQueue。在这篇教程里,我将剖析一个简单的例子来演示怎么来用这些新对象,以及他们怎样在你的应用里加入多线程。

这里可以得到例子工程: Async Downloader Example Project

这篇教程,我将演示其中一种用NSOperation和NSOperationQueue处理一些适合后台运行的任务的方法,这篇教程的目的是演示这些类的基本使用方法,但不是说只有这种唯一的方法使用他们。

如果你对java,或者它的变种熟悉的话,那么可以说,NSOperation 对象很像java.lang.Runnable接口。类似的,在java的Runnable接口中,NSOperation对象被设计为可以扩展的。还是和java一样,这里也有一个方法可以被重载次数的最小值。对于NSOpetation来说,这个方法就是-(void)main.使用NSOperation的最简单的一种方法是把它加入一个NSOperationQueue。一旦operation被加入了这个队列,队列就马上把它踢出开始运行。operation运行结束后,队列就马上将它释放。

NSOperation 例子

在这个例子里,我写了一个NSOperation,在NSOperation里得到一个网页,将这个网页内容保存到一个字符串里,再把它解析到一个NSXMLDocument,然后再完成前,再把NSXMLDocument传回到应用程序的主线程。

PageLoadOperation.h

#import <Cocoa/Cocoa.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) {NSLog(@"%s Error loading document (%@): %@", _cmd, [[self targetURL] absoluteString], error);return;}  [[AppDelegate shared] performSelectorOnMainThread:@selector(pageLoaded:)withObject:documentwaitUntilDone:YES];[document release];
}
@end

就像你看到的,这个类很简单。在初始化方法里接受一个URL,并且保存起来。当main方法被调用的时候,用URL构造一个字符串,然后将这个字符串传到NSXMLDocument的init方法。如果加载xml文档没有出错,就把它传回到AppDelegate,在主线程里,任务完成。当NSOperation的main方法结束,队列将自动释放对象。

AppDelegate.h

#import <Cocoa/Cocoa.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 *)aNotification
{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], queue = nil;[super dealloc];
}
+ (id)shared;
{if (!shared) {[[AppDelegate alloc] init];}return shared;
}
- (void)pageLoaded:(NSXMLDocument*)document;
{NSLog(@"%s Do something with the XMLDocument: %@", _cmd, document);
}
@end

在这个示例AppDelegate里,有两件事发生。第一,在init方法里,NSOperationQueue被初始化,并且有一组url被加载。然后,当应用程序完成了加载,applicationDidFinishLaunching:方法被NSApplication实例调用,AppDelegate在url上循环,为每一个url创建一个任务,并且把这些任务加入NSOperationQueue,一旦每一项加入了队列,队列就马上弹出它赋给一个NSThread,线程将会运行opreation的main方法。一旦operation完成了,线程就马上通知队列,队列就会释放这个operation。

NSOperationQueue 同步

在这个非常简单的例子里,加载足够的对象头查看他们同步运行事十分困难的。但是如果你执行的任务需要比这个花费更多的时间,你就会看到,队列将同时运行所用的任务。幸运的是,如果你想设定同时可以运行的任务数量,你可以修改AppDelegate里的init方法:

- (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];[queue setMaxConcurrentOperationCount:2];shared = self;return self;
}

在这个修改后的init方法里,队列被限制到每次只有两个操作可以同时运行。剩下的操作将不断等待,直到前面的两个操作完成,它们才有机会去运行。

结论

上面是NSOperation 和 NSOperationQueue使用中的基本形式。你会注意到,这个例子中的大部分代码与创建和使用NSOperation 或者 NSOperationQueue毫无关系。实际编码中需要用到的NSOperation很少,但是只要用这少量的代码你就可以轻松的开始在你的应用程序中使用多线程,不但可以给用户提供一份更好的体验,而且可以更好的解决复杂的任务。

(转载)NSOperation and NSOperationQueue教程(翻译)相关推荐

  1. iOS多线程:『NSOperation、NSOperationQueue』详尽总结

    2019独角兽企业重金招聘Python工程师标准>>> iOS多线程:『NSOperation.NSOperationQueue』详尽总结 转载: 原地址https://www.ji ...

  2. Dapper官方教程翻译8:Dapper方法之QueryMultiple(转)

    Dapper官方教程翻译8:Dapper方法之QueryMultiple 2019年02月28日 10:42:22 Day_and_Night_2017 阅读数:120 QueryMultiple方法 ...

  3. Deep Learning 教程翻译

    Deep Learning 教程翻译 非常激动地宣告,Stanford 教授 Andrew Ng 的 Deep Learning 教程,于今日,2013年4月8日,全部翻译成中文.这是中国屌丝军团,从 ...

  4. caffe教程翻译:在caffe上训练与测试数据

    本文为caffe官网上ImageNet教程翻译,地址:http://caffe.berkeleyvision.org/gathered/examples/imagenet.html 本教程旨在教我们用 ...

  5. (转载)Git使用教程:最详细、最傻瓜、最浅显、真正手把手教!

    转载自 Git使用教程 预警:因为详细,所以行文有些长,新手边看边操作效果出乎你的预料) 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 工作原理 / 流程: Workspace: ...

  6. FastAPI 教程翻译 - 用户指南 26 - 安全性

    FastAPI 教程翻译 - 用户指南 26 - 安全性 FastAPI Tutorial - User Guide - Secuity Security Intro 安全性简介 There are ...

  7. pygame 教程翻译---- LGPL许可

    pygame 教程翻译---- LGPL许可 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 版权所有© 1991,1999自 ...

  8. [Reach教程翻译] | 2.3 石头剪刀布

    [Reach教程翻译] Reach是安全简单的Dapp开发语言 让用户可以像开发传统App一样开发DApp 目前使用Reach开发的智能合约可以部署在以太坊.Conflux.Algorand Reac ...

  9. CS231n关于Python使用教程翻译

    CS231n课程笔记翻译:Python Numpy教程 译者注:本文智能单元首发,翻译自斯坦福CS231n课程笔记Python Numpy Tutorial,由课程教师Andrej Karpathy授 ...

最新文章

  1. linux ls 命令只显示目录和只显示文件
  2. Oracle数据库查看用户状态
  3. adams2015安装教程
  4. .NET开发人员犯的6大安全错误
  5. js中的json ajax,js结合json实现ajax简单实例
  6. mvc调用mysql存储过程_使用.NET MVC +EF调用oracle的存储过程
  7. 如何快速上手 angular.js
  8. treetable怎么带参数_VUE treeTable 自定义方法怎么传递
  9. html验证用户名长度,JQuery表单字符串长度验证
  10. overflow c语言_C语言表结构(一)
  11. 【Paper笔记】Complement Objective Training
  12. 大多数程序员单身的原因(转)
  13. 动态规划算法解Travelling Salesman Problem(TSP)问题
  14. Arcgis教程:如何批量统计网格内的线段长度。
  15. 【SSL 1458】zzzyyds(DP)
  16. 笔试题——硬币与金币(概率)
  17. 《 HarmonyOS实战—HarmonyOS(鸿蒙)开发初体验,华为如何引领物联网时代》
  18. Camels【DP】
  19. ARM64之内存屏障
  20. WCF 会话服务 Session

热门文章

  1. 五大常用算法之五:分支限界法
  2. log4j xml配置详解
  3. Protocol Buffer入门——轻松搭建java环境 .
  4. vue ui 启动,浏览器报错Unexpected token
  5. 用第三方工具类,将JavaBean、List、MapString,Object转成JSON文本
  6. Python入门学习笔记11(静态方法、类方法与属性方法)
  7. oracle过滤某个字段重复记录,只获取一条记录
  8. hexo github pages 搭建博客
  9. .SQL Server中 image类型数据的比较
  10. Delphi 7.0常用函数速查手册