NSOperation 取消和 NSOperationQueue
NSOperation cancel and NSOperationQueue
我想了解 NSOperation
子类的正确行为是什么。
我的子类具有不同的 isReady
条件。是的,如果操作被取消,我会检查代码并据此采取行动。当操作正在执行时,这很好。它停止其任务,将 finished
设置为 true 并从队列中删除。但是它的依赖关系呢?它们尚未执行,因此它们永远处于 NSOperationQueue
in cancelled
状态。
我是否应该为取消的操作设置 ready = true
以便队列将调用将在执行中设置的 start 方法并立即完成任务设置 finished
为真?
将执行相关操作。不管a
是否取消。
您应该将 operation.finished==true
设置为最终状态以使 NSOperationQueue
删除 operation
。
您应该在准备好开始 operation
时设置 .ready==true
。
在operation
的生命周期中,你应该经常检查.cancelled
每当.cancelled == true
,你应该停止operation
并设置.finished == true
。
我刚刚自己处理了这个问题。我不明白为什么当我取消我的 NSOperation
子类时,它从未从 NSOperationQueue
中删除。事实证明,我的重写 isReady
方法是罪魁祸首。 isReady
方法正在检查超级实现以及是否设置了 属性,但它没有,这就是操作被取消的原因。但是,显然,如果 NSOperation
实例从未达到就绪状态,即使它被取消,NSOperationQueue
也不会删除该操作,直到达到就绪状态。因此,解决方案是使用 isCancelled
属性 值对您自定义的准备就绪条件进行或运算。或者,您可以更改逻辑,使操作始终准备就绪,但如果未满足就绪条件,则在 main 方法中不执行任何操作,具体取决于您的应用程序逻辑。
示例:
// for proper KVO compliance
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keys = [super keyPathsForValuesAffectingValueForKey:key];
NSString *readyKey = NSStringFromSelector(@selector(isReady));
if ([readyKey isEqualToString:key]) {
keys = [keys setByAddingObjectsFromArray:@[NSStringFromSelector(@selector(url)), NSStringFromSelector(@selector(isCancelled))]];
}
return keys;
}
- (BOOL)isReady
{
return (this.url != nil || this.isCancelled) && super.isReady;
}
- (void)setUrl:(NSURL *)url
{
if (self.url == url) {
return;
}
NSString *urlKey = NSStringFromSelector(@selector(url));
[self willChangeValueForKey:urlKey];
_url = url;
[self didChangeValueForKey:urlKey];
}
感谢NSHipster的KVO article提供以上KVO相关代码
我想了解 NSOperation
子类的正确行为是什么。
我的子类具有不同的 isReady
条件。是的,如果操作被取消,我会检查代码并据此采取行动。当操作正在执行时,这很好。它停止其任务,将 finished
设置为 true 并从队列中删除。但是它的依赖关系呢?它们尚未执行,因此它们永远处于 NSOperationQueue
in cancelled
状态。
我是否应该为取消的操作设置 ready = true
以便队列将调用将在执行中设置的 start 方法并立即完成任务设置 finished
为真?
将执行相关操作。不管a
是否取消。
您应该将 operation.finished==true
设置为最终状态以使 NSOperationQueue
删除 operation
。
您应该在准备好开始 operation
时设置 .ready==true
。
在operation
的生命周期中,你应该经常检查.cancelled
每当.cancelled == true
,你应该停止operation
并设置.finished == true
。
我刚刚自己处理了这个问题。我不明白为什么当我取消我的 NSOperation
子类时,它从未从 NSOperationQueue
中删除。事实证明,我的重写 isReady
方法是罪魁祸首。 isReady
方法正在检查超级实现以及是否设置了 属性,但它没有,这就是操作被取消的原因。但是,显然,如果 NSOperation
实例从未达到就绪状态,即使它被取消,NSOperationQueue
也不会删除该操作,直到达到就绪状态。因此,解决方案是使用 isCancelled
属性 值对您自定义的准备就绪条件进行或运算。或者,您可以更改逻辑,使操作始终准备就绪,但如果未满足就绪条件,则在 main 方法中不执行任何操作,具体取决于您的应用程序逻辑。
示例:
// for proper KVO compliance
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keys = [super keyPathsForValuesAffectingValueForKey:key];
NSString *readyKey = NSStringFromSelector(@selector(isReady));
if ([readyKey isEqualToString:key]) {
keys = [keys setByAddingObjectsFromArray:@[NSStringFromSelector(@selector(url)), NSStringFromSelector(@selector(isCancelled))]];
}
return keys;
}
- (BOOL)isReady
{
return (this.url != nil || this.isCancelled) && super.isReady;
}
- (void)setUrl:(NSURL *)url
{
if (self.url == url) {
return;
}
NSString *urlKey = NSStringFromSelector(@selector(url));
[self willChangeValueForKey:urlKey];
_url = url;
[self didChangeValueForKey:urlKey];
}
感谢NSHipster的KVO article提供以上KVO相关代码