如何自定义一个NSOperation

Foundation framework提供了两个内置的NSOperation的子类,但是这两个内置的operation不一定能够满足我们的实际的需要。比如我们需要一个完成一个网络请求的operation,里面可能会有许多自定义的逻辑在里面,为了完成这些特有的逻辑,往往需要自定义一个NSOperation的子类来。

NSOperation 类本身实现了许多与自定义有关的东西,我们只需要做相对较少的工作就可以了,自定义一个非并发的operation相对简单,只需要处理需要做的逻辑,并且处理cancel 操作就可以,其他的都不需要做了。但是自定义一个并发的operation相对难度较大,需要做的东西也比较多。

If the block operation and invocation operation objects do not quite meet the needs of your application, you can subclass NSOperation directly and add whatever behavior you need. The NSOperation class provides a general subclass point for all operation objects. The class also provides a significant amount of infrastructure to handle most of the work needed for dependencies and KVO notifications. However, there may still be times when you need to supplement the existing infrastructure to ensure that your operations behave correctly. The amount of extra work you have to do depends on whether you are implementing a nonconcurrent or a concurrent operation.

Defining a nonconcurrent operation is much simpler than defining a concurrent operation. For a nonconcurrent operation, all you have to do is perform your main task and respond appropriately to cancellation events; the existing class infrastructure does all of the other work for you. For a concurrent operation, you must replace some of the existing infrastructure with your custom code. The following sections show you how to implement both types of object.

Performing the Main Task

不管是什么类型的operation,必须要做的一件事情就是执行需要的task,这是operation存在的最基本的意义。

At a minimum, every operation object should implement at least the following methods:

1、A custom initialization method

2、main

You need a custom initialization method to put your operation object into a known state and a custom main method to perform your task. You can implement additional methods as needed, of course, such as the following:

1、Custom methods that you plan to call from the implementation of your main method.

2、Accessor methods for setting data values and accessing the results of the operation.

3、Methods of the NSCoding protocol to allow you to archive and unarchive the operation object.

The following code shows a starting template for a custom NSOperation subclass. (This listing does not show how to handle cancellation but does show the methods you would typically have. For information about handling cancellation, see "Responding to Cancellation Events") The initialization method for this class takes a single object as a data parameter and stores a reference to it inside the operation object. The main method would ostensibly work on that data object before returning the results back to your application.

Defining a simple operation object.

@interface MyNonConcurrentOperation : NSOperation

@property id (strong) myData;

- (id)initWithData:(id)data;

@end

@implementation MyNonConcurrentOperation

- (id)initWithData:(id)data {

if(self = [super init]) {

myData = data;

}

return self;

}

- (void)main {

@try {

// Do some work on myData and report the results.

@catch(...) {

// Do not rethrow exceptions.

}

}

@end

For a detailed example of how to implement an NSOperation subclass, see NSOperationSample.

除了添加完成必须工作的main方法之外,还必须要处理cancel相关的逻辑,支持cancel是NSOperation很重要的一部分能力。

Responding to Cancellation Events

After an operation begins executing, it continues performing its task until it is finished or until your code explicitly cancels the operation. Cancellation can occur at any time, even before an operation begins executing. Although the NSOperation class provides a way for clients to cancel an operation, recognizing the cancellation event is voluntary by necessary. If an operation were terminated outright, there might not be a way to reclaim resources that had been allocated. As a result, operation objects are expected to check for cancellation events and to exit gracefully when they occur in the middle of the operation.

To support cancellation in an operation object, all you have to do is call the object‘s isCancelled method periodically from your custom code and return immediately if it ever returns YES. Supporting cancellation is important regardless of the duration of your operation or whether you subclass NSOperation directly or use one of its concrete subclasses. The isCancelled method itself is very lightweight and can be called frequently without any significant performance penalty. When designing your operation objects, you should consider calling the isCalled method at the following places in your code:

1、Immediately before you perform any actual work.

2、At least once during each iteration of a loop, or more frequently if each iteration is relatively long.

3、At any points in your code where it woul be relatively easy to abort the operation.

The following provides a very simple example of how to respond to cancellation events in the main method of an operation object. In this case, the isCancelled method is called each time through a while loop, allowing for a quick exit before work begins and again at regular intervals.

Responding to a cancellation request

- (void)main {

@try {

BOOL isDone = NO;

while(![self isCancelled] && !isDone) {

// Do some work and set isDone to YES when finished

}

}@catch(...) {

// Do not rethrow exceptions.

}

}

Although the preceding example contains no cleanup code, your own code should be sure to free up any resources that were allocated by your custom code.

时间: 2024-12-13 21:49:24

如何自定义一个NSOperation的相关文章

自定义一个类加载器

http://www.cnblogs.com/xrq730/p/4847337.html 为什么要自定义类加载器 类加载机制:http://www.cnblogs.com/xrq730/p/4844915.html 类加载器:http://www.cnblogs.com/xrq730/p/4845144.html 这两篇文章已经详细讲解了类加载机制和类加载器,还剩最后一个问题没有讲解,就是 自定义类加载器.为什么我们要自定义类加载器?因为虽然Java中给用户提供了很多类加载器,但是和实际使用比起

自定义一个处理图片的HttpHandler

有时项目里我们必须将图片进行一定的操作,例如水印,下载等,为了方便和管理我们可以自定义一个HttpHander 来负责这些工作 后台: public class ImageHandler : IHttpHandler { #region IHttpHandler Members public bool IsReusable { get { return true; } } /// <summary> /// 实现IHTTPHandler后必须实现的方法 /// </summary>

Android自定义一个属于自己的时间钟表

1.概述 本文主要讲解的是如何自定义一个时间钟表,通过简单的练习可以简单学习android当中自定义view的一些常用绘图技巧,优化android绘图操作.言归正传,首先看下我们需要实现的效果: 当我们看到这个效果的时候脑子里应该有一定的思路了,我们应该把它分解成以下几个步骤: 1.仪表盘(圆) 2.刻度线(长 中 短) 3.刻度值(1-12) 4.指针(时  分  秒) 5.移动指针,计算指针位置 现在我们已经很清楚自己的思路了,那么我们一个一个来. 第一步:1.自定义View的属性,首先在r

C语言:自定义一个查找字串的功能函数,类似于&lt;string.h&gt;中的strstr()

//自定义一个字符串字串查找标准库函数strstr() #include<stdio.h> #include<string.h> char* myStrstr(char *str1,char *str2); int main() { char *str1 = "hello worl world ld"; char *str2 = " world "; puts(myStrstr(str1,str2)); return 0; } char *m

ExtJs5_继承自定义一个控件

Extjs的开发都可以遵循OOP的原则,其对类的封装也很完善了.自定义一个控件最简单的办法就是继承一个已有的控件.根据上一节的需要,我做了一个Button的子类.首先根据目录结构,在app目录下建立一个ux目录,将自定义控件都放在这个目录下.在ux目录下建立一个文件ButtonTransparent.js. /** * 定义了一个背景透明的Button类,继承于Button */ Ext.define('app.ux.ButtonTransparent', { extend : 'Ext.but

jQuery Validate 表单验证插件----自定义一个验证方法

一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW  访问密码 f224 二.引入依赖包 <script src="../../scripts/jquery-1.3.1.js" type="text/javascript"></script> <script src="lib/jquery.validate.js" type="text/javascript"

自定义一个可以被序列化的泛型Dictionary&lt;TKey,TValue&gt;集合

Dictionary是一个键值类型的集合.它有点像数组,但Dictionary的键可以是任何类型,内部使用Hash Table存储键和值.本篇自定义一个类型安全的泛型Dictionary<TKey, TValue>,并且可以被序列化. 为了使自定义的泛型Dictionary<TKey, TValue>可以被序列化成xml,需要实现泛型IXmlSerializable接口. public class MySerializableDictionary<TKey, TValue&g

自定义一个EL函数

自定义一个EL函数 一般就是一下几个步骤,顺便提供一个工作常用的 案例: 1.编写一个java类,并编写一个静态方法(必需是静态方法),如下所示: public class DateTag { private final static Logger logger = LogManager.getLogger(DateTag.class); private static final long serialVersionUID = -2312310581852395045L; public stat

SpringMVC 自定义一个拦截器

自定义一个拦截器方法,实现HandlerInterceptor方法 public class FirstInterceptor implements HandlerInterceptor{ /** * 该方法在目标方法之前被调用. * 若返回值为 true, 则继续调用后续的拦截器和目标方法. * 若返回值为 false, 则不会再调用后续的拦截器和目标方法. * * 可以考虑做权限. 日志, 事务等. */ @Override public boolean preHandle(HttpServ