Eri*_*rik 24 macos nsoperation ios swift
我NSOperation在Swift中进行子类化,需要覆盖isExecuting和isFinished属性,因为我重写了start方法.
我遇到的问题是如何保留键值观察(KVO),同时还能够覆盖这些属性.
通常在Obj-C中,这很容易重新声明属性,就像readwrite在类扩展JSONOperation ()定义中一样.但是,我没有在Swift中看到同样的功能.
例:
class JSONOperation : NSOperation, NSURLConnectionDelegate
{
var executing : Bool
{
get { return super.executing }
set { super.executing } // ERROR: readonly in the superclass
}
// Starts the asynchronous NSURLConnection on the main thread
override func start()
{
self.willChangeValueForKey("isExecuting")
self.executing = true
self.didChangeValueForKey("isExecuting")
NSOperationQueue.mainQueue().addOperationWithBlock(
{
self.connection = NSURLConnection(request: self.request, delegate: self, startImmediately: true)
})
}
}
Run Code Online (Sandbox Code Playgroud)
所以这是我提出的解决方案,但它感觉非常丑陋和hacky:
var state = Operation()
struct Operation
{
var executing = false
var finished = false
}
override var executing : Bool
{
get { return state.executing }
set { state.executing = newValue }
}
override var finished : Bool
{
get { return state.finished }
set { state.finished = newValue }
}
Run Code Online (Sandbox Code Playgroud)
请告诉我有更好的方法.我知道我可以创建一个var isExecuting而不是整个struct,但后来我有两个类似命名的属性,它们引入了歧义并且也使它公开可写(我不想要).
哦,我会为一些访问修饰符关键字做...
Rob*_*Rob 29
正如David所说,您可以在子类属性覆盖中实现getter和setter.
但是,在定义asynchronous/ concurrent操作(即那些将异步完成的操作)时,调用will/ didChangeValueForKeyfor isFinished和是至关重要的isExecuting.如果不这样做,操作将不会被释放,依赖关系将不会被尊重,您将遇到问题maxConcurrentOperationCount,等等.
所以我建议:
private var _executing: Bool = false
override var executing: Bool {
get {
return _executing
}
set {
if _executing != newValue {
willChangeValueForKey("isExecuting")
_executing = newValue
didChangeValueForKey("isExecuting")
}
}
}
private var _finished: Bool = false;
override var finished: Bool {
get {
return _finished
}
set {
if _finished != newValue {
willChangeValueForKey("isFinished")
_finished = newValue
didChangeValueForKey("isFinished")
}
}
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,检查,看看是否_executing和_finished已经改变并不重要,但编写自定义时,它有时是有用的cancel方法等.
更新:
不止一次,人们已经指出新的finished/ executing属性,NSOperation.h并得出结论,适当的KVO键将是finished/ executing.通常,在编写符合KVO标准的属性时,这是正确的.
但是NSOperationQueue没有观察finished/ executing键.它观察isFinished/ isExecuting键.如果不对isFinished/ isExecutingkeys 执行KVO调用,则可能会出现问题(特别是异步操作之间的依赖关系将失败).这很烦人,但这就是它的工作原理." 并发编程指南"的" 操作队列"一章的" 配置并发执行操作"部分非常清楚需要执行isFinished/ isExecutingKVO调用的主题.
虽然并发编程指南已过时,但它对isFinished/ isExecutingKVO 非常明确.并且可以轻松地凭经验验证指南仍然反映实际NSOperation实施.通过演示,在使用异步/并发子类时,请参阅此Github演示中适当KVO的单元测试.NSOperationNSOperationQueue
Dav*_*rry 24
从快速的书:
通过在子类属性覆盖中提供getter和setter,可以将继承的只读属性作为读写属性提供.
我想你会发现这个有效:
override var executing : Bool {
get { return _executing }
set {
willChangeValueForKey("isExecuting")
_executing = newValue
didChangeValueForKey("isExecuting")
}
}
private var _executing : Bool
Run Code Online (Sandbox Code Playgroud)
Mar*_*ark 10
Swift 3.0答案更新:
private var _executing : Bool = false
override var isExecuting : Bool {
get { return _executing }
set {
guard _executing != newValue else { return }
willChangeValue(forKey: "isExecuting")
_executing = newValue
didChangeValue(forKey: "isExecuting")
}
}
private var _finished : Bool = false
override var isFinished : Bool {
get { return _finished }
set {
guard _finished != newValue else { return }
willChangeValue(forKey: "isFinished")
_finished = newValue
didChangeValue(forKey: "isFinished")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7682 次 |
| 最近记录: |