2016-08-12 68 views
1

我用this指南使我的应用程序使用NSOperationQueue和NSOperations。但是我的代码仍然在主线程上运行,不管:S?我必须说我是NSOperation的新手,我认为这是我错过的一件小事。在主线程上运行NSOperation

class CountryFetcher: NSObject{ 
    var operation: NSOperation? 
    var alamoFireQueue: NSOperationQueue{ 
     let val = NSOperationQueue() 
     val.maxConcurrentOperationCount = 10 
     val.name = "Alamofire Downloading Queue" 
     return val 
    } 

    func getCountries(){ 
     operation = CountryProcessor(URLString: (BASE_URL + "countries/"+CAT_STAMPS)) 
     alamoFireQueue.addOperation(operation!) 
    } 
} 

class CountryProcessor : ConcurrentOperation { 
    let URLString: String 
    weak var request: Alamofire.Request? 


    init(URLString: String) { 
     self.URLString = URLString 
     super.init() 
    } 

    override func main() { 
     request = Alamofire.request(.GET, URLString).responseJSON { response in 
      if let dataResponse = response.data{ 
       var test: NSArray? 
       do{ 
        test = try NSJSONSerialization.JSONObjectWithData(dataResponse, options: NSJSONReadingOptions()) as! NSArray 
       }catch let error as NSError{ 
        print(error.localizedDescription) 
       } 
       for _ in 1...100{ 
         NSLog("main thread? %@", NSThread.isMainThread() ? "YES" : "NO"); 
       } 
      } 
      self.completeOperation() 
     } 
    } 

    override func cancel() { 
     request?.cancel() 
     super.cancel() 
    } 
} 

这是ConcurrentOperation类。我在上面的链接中从帖子中复制了它。

class ConcurrentOperation : NSOperation { 

    override var asynchronous: Bool { 
     return true 
    } 

    override var concurrent: Bool{ 
     return true 
    } 

    private var _executing: Bool = false 
    override var executing: Bool { 
     get { 
      return _executing 
     } 
     set { 
      if (_executing != newValue) { 
       self.willChangeValueForKey("isExecuting") 
       _executing = newValue 
       self.didChangeValueForKey("isExecuting") 
      } 
     } 
    } 

    private var _finished: Bool = false; 
    override var finished: Bool { 
     get { 
      return _finished 
     } 
     set { 
      if (_finished != newValue) { 
       self.willChangeValueForKey("isFinished") 
       _finished = newValue 
       self.didChangeValueForKey("isFinished") 
      } 
     } 
    } 

    /// Complete the operation 
    /// 
    /// This will result in the appropriate KVN of isFinished and isExecuting 

    func completeOperation() { 
     executing = false 
     finished = true 
    } 

    override func start() { 
     if (cancelled) { 
      finished = true 
      return 
     } 

     executing = true 

     main() 
    } 
} 

当我执行这个代码,它口口声声说其运行的主线程上:2016年8月12日18:25:45.799邮票Catalague预加载[1807:31357]主线程?是。

这是怎么发生的?谢谢你的帮助;

+0

你可能已经从[这里]得到了'NSOperation'的子类,但是我已经更新了它(http://stackoverflow.com/questions/27021896/nsurlsession-concurrent-requests-with-alamofire/27022598#27022598)同步执行和完成的getter和setter。请参阅[多核考量](https://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSOperation_class/index.html#//apple_ref/doc/uid/TP40004591-RH2-SW17)讨论哪些会谈关于同步这些的重要性。 – Rob

+0

另外,由于您使用'responseJSON',因此不需要调用'NSJSONSerialization'。这已经为你完成了。 (这就是我们使用'responseJSON'的原因,所以我们不必担心自己解析它。)只需使用'response.result.value'。 – Rob

回答

1

问题是,Alamofire将其完成处理程序分派到主队列中(理论上说,他们想让您更容易更新UI和/或模型)。

如果要为完成处理程序使用不同的队列,请将队列参数提供给responseresponseJSON方法。

例如,有一些特性:

var completionHandlerQueue = dispatch_queue_create("com.domain.completionhandler", nil) 

然后,当你执行的要求:

Alamofire.request(.GET, URLString).responseJSON(queue: completionHandlerQueue) { response in 
    guard let test = response.result.value else { 
     print("no data") 
     print(response.result.error) 
     return 
    } 

    // do something with `test` here 
    print(test) 

    NSLog("main thread? %@", NSThread.isMainThread() ? "YES" : "NO"); 
} 

这引起了你是否真正关心的问题,如果完成处理在主队列上被调用或不被调用。当然,如果你在那里进行一些计算密集型的工作,那么通过一切手段,指定一个不同的队列。但是没有任何理由说明操作无法在主队列上执行某些任务。事实上,有时只需要在主队列上运行完成处理程序就会非常有用,从而避免了需要同步模型更新和/或将UI更新发送到主队列。

要退一步,我们必须问一下使用NSOperation的意图是什么。如果目标仅仅是享受异步处理请求,则不需要NSOperation。但是,如果(a)您使用NSOperation来管理不同操作的依赖关系;和(b)你没有使用后台会话,那么,无论如何,将你的请求包装在操作中。

相关问题