我正在使用包含块的初始化程序创建我的NSOperation
子类:
let concurrentOperation = ABOConcurrentOperation {[weak weakOp = concurrentOperation] in
...
}
不幸的是,这不起作用,因为我总是得到对我有意义的错误消息Variable used within its own initial value
,但是......我如何才能将concurrentOperation作为弱引用?
答案 0 :(得分:1)
如果您需要引用块中的操作,则应将其作为参数传递给闭包,然后您不需要weak
引用。它会在闭包完成时自动解析引用。例如,请考虑以下事项:
let queue = NSOperationQueue()
let concurrentOperation = ABOConcurrentOperation() { operation in
print("\(NSDate()): starting operation")
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * Int64(NSEC_PER_SEC)), dispatch_get_main_queue()) {
print("\(NSDate()): finishing operation")
operation.completeOperation()
}
}
queue.addOperation(concurrentOperation)
而且,我将闭包定义为标准闭包:
private var block: ((AsynchronousOperation) -> ())? // FYI, I use optional in case the caller accidentally introduces a strong reference cycle, I can resolve that when the operation completes.
如果您的子类在deinit
中打印了某些内容:
/// a subclass that will just confirm that `deinit` is called
class ABOConcurrentOperation: AsynchronousBlockOperation {
deinit {
print("deinit")
}
}
您会看到发生了什么:
2016-07-07 21:20:54 +0000:开始操作
2016-07-07 21:21:01 +0000:整理操作
DEINIT
供您参考,这是上面使用的示例AsynchronousOperation
类:
/// Asynchronous Operation base class
///
/// This class performs all of the necessary KVN of `isFinished` and
/// `isExecuting` for a concurrent `NSOperation` subclass. So, to developer
/// a concurrent NSOperation subclass, you instead subclass this class which:
///
/// - must override `main()` with the tasks that initiate the asynchronous task;
///
/// - must call `completeOperation()` function when the asynchronous task is done;
///
/// - optionally, periodically check `self.cancelled` status, performing any clean-up
/// necessary and then ensuring that `completeOperation()` is called; or
/// override `cancel` method, calling `super.cancel()` and then cleaning-up
/// and ensuring `completeOperation()` is called.
public class AsynchronousOperation : NSOperation {
override public var asynchronous: Bool { return true }
private let stateLock = NSLock()
private var _executing: Bool = false
override private(set) public var executing: Bool {
get {
return stateLock.withCriticalScope { _executing }
}
set {
willChangeValueForKey("isExecuting")
stateLock.withCriticalScope { _executing = newValue }
didChangeValueForKey("isExecuting")
}
}
private var _finished: Bool = false
override private(set) public var finished: Bool {
get {
return stateLock.withCriticalScope { _finished }
}
set {
willChangeValueForKey("isFinished")
stateLock.withCriticalScope { _finished = newValue }
didChangeValueForKey("isFinished")
}
}
/// Complete the operation
///
/// This will result in the appropriate KVN of isFinished and isExecuting
public func completeOperation() {
if executing {
executing = false
}
if !finished {
finished = true
}
}
override public func start() {
if cancelled {
finished = true
return
}
executing = true
main()
}
override public func main() {
fatalError("subclasses must override `main`")
}
}
/// Asynchronous Operation base class
///
/// This class lets you perform asynchronous block operation. Make sure that the
/// the provided `block` calls `completeOperation`, or else this operation will
/// never finish.
public class AsynchronousBlockOperation : AsynchronousOperation {
private var block: ((AsynchronousOperation) -> ())?
init(block: (AsynchronousOperation) -> ()) {
self.block = block
super.init()
}
override public func main() {
block?(self)
}
override public func completeOperation() {
block = nil
super.completeOperation()
}
}
extension NSLock {
/// Perform closure within lock.
///
/// An extension to `NSLock` to simplify executing critical code.
///
/// - parameter block: The closure to be performed.
func withCriticalScope<T>(@noescape block: Void -> T) -> T {
lock()
let value = block()
unlock()
return value
}
}
答案 1 :(得分:0)
代码(正如你所写的那样)带来了“鸡肉或鸡蛋”的情景。试试这个:
var concurrentOperation: ((foo) -> bar)! //insert correct type annocation here
concurrentOperation = ABOConcurrentOperation {
//use concurrentOperation here
}