I am trying to confirm or debunk a feeling I have about NSOperation in that it can't be used for networking threads. Basically I am making a Cocoa App that connects to del.icio.us. When I thought about spawning the network threads I thought i'd try and experiment with NSOperation since I am on Leopard. I created a NSOperation subclass that in short creates a NSURLConnection with user credentials and assigns itself as a delegate to download the users last update time and return that. My Problem arises when I get to this bit of code inside my NSOperation subclasses main method
// Run the runLoop for a few seconds to give the connection request a chance [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
after that 1 of 2 things happens... (1) the app crashes deep inside apples code or (2) it comes back with the html code of a page saying that I am not authenticated. When exploring the stack it looks like the application is behaving in such a way that NSURLConnection is getting started but when the data is finally being returned from del.icio.us it's like the memory for the thread has been yanked out from beneath the thread as if it just continued on regardless and ignored my code to keep running. I've tried several things to keep the thread running and everytime either (1) or (2) happens. I've been searching everywhere for an example of NSOperation being used in network operations, but can't so far and haven't found anything explicit in the documentation about network operations.
In short can NSOperation be used as a network thread? If so am I trying to keep it running while it waits for a return response in a totally wrong way?
If it's needed I'll post the full source code later, but for now I thought i'd find out the short answer to NSOperation being used in network threads first. Thank you very much for your help in advance!
Yes, you can do networking in an NSOperation. I have done the same thing (but using NSURLDownload). One difference is that I'm doing NSRunLoop#runMode:NSDefaultRunLoopMode beforeDate:<date> instead of runUntilDate:.
I had a problem that took several hours to diagnose in http://cocoadev.com/forums/comments.php?DiscussionID=5&page=1#Item_3. Take a look and see if the errors look familiar to the ones you see. What was ultimately happening was that I had been storing the NSURLResponse given in the #download:didReceiveResponse: delegate method in a property in my delegate class, and it appeared to be getting garbage collected. I removed the reference and just stored the data I needed (content length) in a scalar field and the problems went away.
Well my problem is a bit different. I did try running it in the runloop mode mentioned above but I see 1 big problem either way I run it
I see the NSURLConnection delegate method that says I received the data going off, but the authentication challenge never goes off and confuses the heck out of me. I've uploaded the full project to my site here ( http://www.1729.us/source/NetOperation.tbz ) if you want to run it.
// Run the runLoop for a few seconds to give the connection request a chance [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
//while (self.urlData == nil) { // NSLog(@"Extending the run loop by 5 seconds"); // [[NSRunLoop currentRunLoop] runMode:@"NSDefaultRunLoopMode" // beforeDate:[NSDate dateWithTimeIntervalSinceNow:20]]; //} }
not sure if you're still having this problem, but i had a similar problem of my delegate's not being around by the time data came back after i added in NSOperation.
basically i was creating 20 - 30 NSURLConnections, which were locking up the main thread, so i added the tasks to NSOperationQueue as NSInvocationOperation objects (which may or may not be ideal for you).
anyway it never worked and it turned out that since i was doing the urlconnections asynchronously things were getting collected before the data was returning. i solved my problem by using NSURLConnections <code> sendSynchronousRequest:urlRequest returningResponse:&urlResponse error:&errorCode </code>
and made the calls synchronously, since they were already threaded with NSOperationQueue anyway. works better than i anticipated, but may or may not do what you want.