Reputation: 385
I've used this guide to make my app use NSOperationQueue and NSOperations. But my code still runs on the main thread regardless :S? I must say that I'm new to NSOperation, I think it is a small thing that I missed.
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()
}
}
This is the ConcurrentOperation class. I copied it from the post in the link above.
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()
}
}
When I execute this code, it keeps saying that it runs on the main thread: 2016-08-12 18:25:45.799 Stamp Catalague Preloader[1807:31357] main thread? YES.
How is this happening? Thanks for your help;
Upvotes: 1
Views: 756
Reputation: 438232
The issue is that Alamofire dispatches its completion handlers to the main queue (the theory being that they want to make it easy for you to update the UI and/or model).
If you want to use a different queue for the completion handlers, supply the queue parameter to the response
or responseJSON
methods.
For example, have some property:
var completionHandlerQueue = dispatch_queue_create("com.domain.completionhandler", nil)
And then, when you perform the request:
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");
}
This raises the question of whether you really care if the completion handlers are called on the main queue or not. Sure, if you're doing something computationally intensive there, then, by all means, specify a different queue. But there's no reason why an operation can't perform some of its tasks on the main queue. In fact, it's awfully useful at times to just have the completion handlers run on the main queue, saving you from needing to synchronize your model updates and/or dispatch your UI updates to the main queue.
To step back even further, we have to ask what the intent of using NSOperation
is. If the goal is merely to enjoy asynchronous processing of requests, NSOperation
is not needed. But if (a) you're using NSOperation
to manage dependencies of different operations; and (b) you're not using background sessions, then, by all means, wrap your requests in operations.
Upvotes: 1