Переопределяет свойство NSOperation (isExecuting / isFinished)
я подклассы NSOperation
в Swift и нужно переопределить isExecuting
и isFinished
свойства, так как я переопределяя start
метод.
проблема, с которой я сталкиваюсь, заключается в том, как сохранить наблюдение за значением ключа (KVO), а также переопределить эти свойства.
обычно в Obj-C это было бы довольно легко переопределить свойства как readwrite
в расширении класса JSONOperation ()
определение. Однако я не вижу такой же возможности в Быстрый.
пример:
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)
})
}
}
Итак, вот решение, которое я придумал, но оно кажется ужасно уродливым и избитым:
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 }
}
Пожалуйста, скажите мне, что есть лучший путь. Я знаю, что могу сделать var isExecuting
вместо всего struct
, но тогда у меня есть два одноименных свойства, которые вводят двусмысленность, а также делают его общедоступным для записи (чего я не хочу).
о, что бы я сделал для некоторых ключевых слов модификатора доступа...
3 ответов
из книги swift:
наследуемое свойство только для чтения можно представить как свойство чтения и записи, предоставив как геттер, так и сеттер в переопределении свойства подкласса.
Я думаю, вы обнаружите, что это работает:
override var executing : Bool {
get { return _executing }
set {
willChangeValueForKey("isExecuting")
_executing = newValue
didChangeValueForKey("isExecuting")
}
}
private var _executing : Bool
как сказал Дэвид, вы можете реализовать как геттер, так и сеттер в переопределении свойства подкласса.
но, при определении asynchronous
/concurrent
операции (т. е. те операции, которые будут выполняться асинхронно), важно назвать will
/didChangeValueForKey
на isFinished
и isExecuting
. Если вы этого не сделаете, операции не будут выпущены, зависимости не будут соблюдены, у вас будут проблемы maxConcurrentOperationCount
, etc.).
поэтому я бы предлагаю:
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")
}
}
}
кстати, проверяя, если _executing
и _finished
изменились не критично, но иногда это может быть полезно при написании пользовательского cancel
методы или тому подобное.
обновление:
не раз люди указывали на новое finished
/executing
свойства NSOperation.h
и пришел к выводу, что соответствующие ключи KVO будут finished
/executing
. Как правило, при написании свойств, совместимых с KVO, это было бы правильно.
но NSOperationQueue
не наблюдает finished
/executing
ключи. отмечается isFinished
/isExecuting
ключи. Если вы не выполняете вызовы KVO для isFinished
/isExecuting
ключи, у вас могут быть проблемы (в частности, зависимости между асинхронными операциями не удастся). Это раздражает, но так это работает. The настройка операций для параллельного выполнения на Очереди Операции глава Руководство По Программированию Параллелизма очень ясно на тему необходимости выполнения isFinished
/isExecuting
кво звонки.
пока Руководство По Программированию Параллелизма датировано, это довольно ясно относительно isFinished
/isExecuting
кво. И можно легко эмпирически подтвердить, что руководство по-прежнему отражает фактическое NSOperation
реализация. В качестве демонстрации см. модульные тесты в это GitHub демонстрация соответствующего кво при использовании асинхронного / параллельного NSOperation
подкласс в NSOperationQueue
.
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")
}
}