2015-10-29 5 views
1

У меня есть этот код, чтобы добавить NSOperation экземпляр очередьПочему мой NSOperation не отменяет?

let operation = NSBlockOperation() 
operation.addExecutionBlock({ 
    self.asyncMethod() { (result, error) in 
     if operation.cancelled { 
      return 
     } 

     // etc 
    } 
}) 
operationQueue.addOperation(operation) 

Когда пользователь покидает представление, которое инициировало этот код выше я отменить операцию делать

operationQueue.cancelAllOperations() 

При тестировании гашения, я 100 % sure cancel выполняется до того, как метод async вернется, поэтому я ожидаю, что operation.cancelled будет правдой. К сожалению, этого не происходит, и я не в состоянии понять, почему

Я выполнение отмены на viewWillDisappear

EDIT

asyncMethod содержит сетевую операцию, которая работает в другом потоке. Вот почему обратный вызов есть: для обработки возвратов операции сети. Операция сети выполняется глубоко в иерархии классов, но я хочу обрабатывать NSOperations на корневом уровне.

+0

Вы должны быть уверены, что операция.cancelled истинна перед тестом, а не только перед возвратом метода async ... – user3441734

+0

@ user3441734: что вы имеете в виду под «перед тестом»? Невозможно, чтобы операция была отменена до начала асинхронного метода, поскольку логики нет. Если он отменен раньше, он просто не будет запускаться. – StackOverflower

+0

«Я на 100% уверен, что отмена выполняется до того, как метод async вернется, поэтому я ожидаю, что операция будет исправлена». метод async вернется, хотя операция.cancelled будет ложной. он просто не возвращается «рано». – user3441734

ответ

2

Вызов метода отмены этого объекта устанавливает значение этого свойства в поле YES. После отмены операция должна перейти в состояние .

Отмена операции не приводит к активной остановке кода приемника от . Объект операции отвечает за вызов этого метода периодически и остановку самого себя, если метод возвращает YES.

Вы должны всегда проверять значение этого свойства перед выполнением любых работ для выполнения задачи операции, которая обычно означает , проверяя ее в начале вашего основного основного метода. возможно для операции, которая должна быть отменена до того, как она начнет выполнение или в любое время во время ее выполнения. Поэтому, проверяя значение на , начало вашего основного метода (и периодически по всему этому методу ) позволяет вам как можно быстрее выйти, когда операция отменена.

import Foundation 

let operation1 = NSBlockOperation() 
let operation2 = NSBlockOperation() 
let queue = NSOperationQueue() 
operation1.addExecutionBlock {() -> Void in 
    repeat { 
     usleep(10000) 
     print(".", terminator: "") 
    } while !operation1.cancelled 
} 
operation2.addExecutionBlock {() -> Void in 
    repeat { 
     usleep(15000) 
     print("-", terminator: "") 
    } while !operation2.cancelled 
} 
queue.addOperation(operation1) 
queue.addOperation(operation2) 
sleep(1) 
queue.cancelAllOperations() 

попробовать этот простой пример на детской площадке.

, если это действительно важно, чтобы запустить другой асинхронный код, попробуйте это

operation.addExecutionBlock({ 
if operation.cancelled { 
      return 
     }  
self.asyncMethod() { (result, error) in 


     // etc 
    } 
}) 
+0

Правильно прочитайте мой вопрос. Я проверяю значение 'canceled'. Моя проблема заключается в том, что всегда «ложь», даже когда я отменил операцию – StackOverflower

+0

, если ваш self.asyncMethod() действительно является асинхронным, он немедленно возвращается, и блок выполнения также немедленно завершается. Я обновил свой ответ с помощью очень простого примера, как использовать NSOperation и NSOperationQueue. – user3441734

+0

. Я ценю, что вы вкладываете все это вместе, но я не вижу разницы между моим кодом и вашим. Я отправил отладчик в очередь после отмены операции и обратного вызова метода async, я подтвердил, что отмена выполняется до 'if operation.отменено, но отменено остается в 'false' – StackOverflower

0

Я не 100% уверен, что вы ищете, но, возможно, что вам нужно будет пройти операцию, в качестве параметра, в asyncMethod() и проверить отмененное состояние там?

operation.addExecutionBlock({ 
    asyncMethod(operation) { (result, error) in 
    // Result code 
    } 
}) 
operationQueue.addOperation(operation) 

func asyncMethod(operation: NSBlockOperation, fun: ((Any, Any)->Void)) { 
    // Do stuff... 
    if operation.cancelled { 
    // Do something... 
    return // <- Or whatever makes senes 
    } 
} 
3

это потому, что вы работаете неправильно. Вы отменя операцию после ее выполнения. Проверьте этот код, блок выполняется в одном фоновом потоке. Перед запуском запуска - отмените операцию, удалите первый блок из очереди.

Swift 3

Скоро

Swift 2

let operationQueue = NSOperationQueue() 
operationQueue.qualityOfService = .Background 

let ob1 = NSBlockOperation() 
ob1.addExecutionBlock { 
    print("ExecutionBlock 1. Executed!") 
} 

let ob2 = NSBlockOperation() 
ob2.addExecutionBlock { 
    print("ExecutionBlock 2. Executed!") 
} 

operationQueue.addOperation(ob1) 
operationQueue.addOperation(ob2) 

ob1.cancel() 

// ExecutionBlock 2. Executed! 
1

операция не ждет вашего asyncMethod быть закончена. Поэтому он немедленно возвращается, если вы добавляете его в очередь. И это связано с тем, что вы завершаете операцию асинхронной сети в async NSOperation.

NSOperation предназначен для более совершенной обработки асинхронных сообщений вместо того, чтобы просто позвонить performSelectorInBackground. Это означает, что NSOperation используется для выполнения сложных и длительных операций в фоновом режиме, а не для блокировки основного потока. Хорошая статья типично используется NSOperation можно найти здесь:

http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues

Для вашего конкретного случая использования, это не имеет смысла использовать NSOperation здесь, вместо этого вы должны просто отменить запрос работает в сети.

1

Не имеет смысла помещать асинхронную функцию в блок с NSBlockOperation. Возможно, вам нужен соответствующий подкласс из NSOperation как параллельная операция, выполняющая асинхронную рабочую нагрузку. Подклассификация NSOperationправильно, однако, не так просто, как должно.

Вы можете посмотреть здесь reusable subclass for NSOperation для примера реализации.

Смежные вопросы