首页 > 代码库 > 如何自定义一个NSOperation

如何自定义一个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 = http://www.mamicode.com/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.










如何自定义一个NSOperation