Wenn Sie einen Verweis auf den Betrieb im Block benötigen, können Sie es als Parameter an die Schließung passieren sollte und dann brauchen Sie keinen weak
Referenz. Die Referenz wird automatisch aufgelöst, wenn die Schließung abgeschlossen ist. Betrachten wir zum Beispiel die folgende:
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)
Und ich diesen Verschluss definiert ein Standard-Verschluss zu sein:
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.
Wenn Sie Ihre Unterklasse, die etwas in deinit
druckt:
/// a subclass that will just confirm that `deinit` is called
class ABOConcurrentOperation: AsynchronousBlockOperation {
deinit {
print("deinit")
}
}
Sie werden sehen, was passiert:
2016.07.07 21.20.54 0.000: Anfahrvorgang
2016.07.07 21.21.01 0.000: Schlichten
deinit
Zu Ihrer Information, das ist die Probe AsynchronousOperation
Klasse verwendet oben:
/// 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
}
}
http://stackoverflow.com/a/30523666/3141234 – Alexander
es scheint, als ob ich tun ein Zyklus beibehalten, wie der Betrieb nicht freigegeben bekommt - mein Kommentar über die Antwort sehen von @AMomchilov – swalkner
Rückblickend ist das Problem, dass Sie anscheinend versuchen, die Operation in der Schließung. Die Lösung besteht darin, dass die Operation selbst einen Verweis auf sich selbst als Parameter übergibt. Siehe die überarbeitete Diskussion in meiner Antwort unten. – Rob