问题
I have an IPhone app that uses webservices to get data from a server. I'm putting each call to the webservice in a NSOperation subclass so that it can be threaded. My question is, what is the recommended way to pass back information from a completed NSOperation subclass. I'm currently sending a NSNotification at the end of my main method and any code that is waiting for the NSOperation to complete, subscribes to the notification. And then I will use the object part of NSNotificationWithName:Object: to pass information back from the operation.
I wasn't sure if there was a better way to do this. I have heard of Key Value Coding and then I could use Key Value Observing to detect when the the isFinished property for the operation is changed, but I'm not sure what the best practice is.
I'm also trying to ensure that my application is thread safe, which I assume wouldn't be an issue as long as a my notification was sent out at the end of the main method thus the object in the notification would no longer be used in the thread since it will end.
Finally, I am calling the notification like so:
[[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:[NSNotification notificationWithName:@"notificationName" object:dataObject] waitUntilDone:NO];
回答1:
I've personally done this in two ways. Both worked quite well.
First Way
You can have a function that returns the "output", and you call that function after the operation has finished. You can observe the key isFinished
on the NSOperation
object, or use -[NSOperationQueue waitUntilAllOperationsAreFinished]
to determine when the operation is finished.
Second Way
You can use a delegate or target/action from the NSOperation. Just make sure that when you call the delegate function, or trigger the target/action, you do so on the main thread by using -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:]
回答2:
It depends on your application. How many of the operations do you expect to run concurrently? What are you doing with the result? Are results aggregated or do they need to display in the UI immediately?
Sending notifications on the main thread is fairly heavyweight. Depending on what you're doing with the result, you could choke up your UI. From a design perspective, are the objects that you would be sending from the notification something that the observing class should know about? It may make more sense to make changes to your model objects from the operation and have a controller object observe those changes instead.
You could use Key Value Observing but you must be careful. The observer observes in the same thread that the change occurs on, so you should not make UI changes directly when observing isFinished.
If the object is only owned and used by the operation, then yes, it should be safe to send at the end of main. It will be retained by the notification.
回答3:
The doc says it's better to make the operation member variable when you want get the result from operation. But I do not think the solution will adapt you.
I think notification is good and There is another way to get the result is make a completion block for your own operation.See here: Return data from NSOperation? I tried it's work well.
I tried another way before.set the operation completion block,and make a weak reference to operation and make the result an property of operation. so you can get the operation result when you finished.
But completion is not reliable,when you cancel the operation the completion excuted too. so choose the best for you.
来源:https://stackoverflow.com/questions/1297733/cocoa-return-information-from-nsoperation