Slow closing of UIDocument - iphone

I have an application with my UIDocument subclass. But the problem is that from time to time method closeWithCompletionHandler works too long. I even can't wait until the end, it takes too much time. The thing is when I put a breakpoint in - (id)contentsForType:(NSString *)typeName error:(NSError **)outError method, everything works fine. So, the question is what can cause such effect?
Thanks!

Is this code running on the main thread? If that's the case, try running it in a background thread using a dispatch queue.
Note that the main thread powers the UI drawing as well, which is why your app gets stuck when the main thread has too much work to do. Therefore, it is always advisable to put larger operations into a background thread.

Related

NSOperationQueue waitUntilAllOperationsAreFinished vs. performSelectorOnMainThread

I have background NSInvocationOperation creating and saving NSArray to the NSManagedObject subclass.
I know that save should happen on main thread, so I use performSelectorOnMainThread for save in the operation.
When user pushes home button on iPhone 3G, app is going to quit. In applicationDidEnterBackground I do [queue waitUntilAllOperationsAreFinished], so that NSInvocationOperation has time to finish.
The problem is, that it waits only for "background part" of the operation - app is shutted down before performSelectorOnMainThread part of the operation is called. This means my NSManagedObject is not saved.
I tried to save object in operation's thread - app is shutted gracefully and changes are saved. But I think this is not good as NSManagedObject is not thread safe. Or is it OK to do this?
It seems like catch 22. I must be missing something - is there any elegant way how to solve this?
You should just do the save operation in the background using a separate context that notifies the main context. This means creating, fetching, and saving managed objects should be done on this separate context and this is documented in the Core Data - Concurrency with Core Data. You should also start a background task to ensure you have enough time to finish saving the data.

NSOperation finishes in the background, attempts to notify main thread, view no longer exists. Crash

I have an NSOperation running not in the main thread. It is spawned from a UITableViewController. When the operation is complete, I'd like to reload the tableview since some data has changed. I've set a delegate for the background to notify on completion. When done, I call a wrapper around reloadData specifically on the main thread using performSelectorOnMainThread.
For the most part, this works well, however, there is a non-0 chance that the original (edit)tableViewController (/edit) gets released and I get zombie calls.
So the question is in 2 parts:
Is it possible to have a delegate from the background thread without retaining the object?
Is this just a bad design? Should I be using NSNotifications instead? Would that be the preferred method of notifying in this case?
Thanks in advance.
A delegate should be retained if there is a possibility that it might be released before any operation on the delegate is invoked. You can set up a state in tableViewController to handle the case when the delegate callback is invoked and the tableViewController is not to be used (Basically make the callbacks act as no-op). Once your operation is done, just release the delegate object.
It is not a bad design but you just need to handle these conditions.

iphone - what is the logic of this kind of multithread operation

I am just trying to understand this: multithread is a way of firing a method in another thread, so it will not hang the main thread (when something heavy must be done). But I have seen stuff like this:
this goes on the main code:
[NSThread detachNewThreadSelector:#selector(createNewThread) toTarget:self withObject:nil];
and here goes the thread
-(void) createNewThread {
NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init];
[self performSelectorOnMainThread:#selector(doSomeStuff) withObject:nil waitUntilDone:YES];
[p release];
}
My problem with this is: if the thread is intended to relieve the main thread from doing something, why is doSomeStuff being called using performSelectorOnMainThread? Isn't that insane? I mean, you fire a second thread just to run something on the main thread, a thread that in fact you shouldn't be using.
I have seen a lot of code on the web write this way.
I know that probably it is done that way because it is doing something that is not thread safe, but is doing this really useful? To me sounds that it is totally useless and it would be better to do something like
[self performSelector:#selector(doSomeStuff) withObject:nil afterDelay:0.01];
what do you guys think?
thanks in advance.
performSelectorOnMainThread:withObject:waitUntilDone: puts the call on a queue to perform on the next iteration of the run loop. performSelector:withObject:afterDelay: sets up a timer to perform the action. However, creating a new thread to call performSelectorOnMainThread makes no sense because it puts the call on the queue even if it is already on the main thread.
If that's the entire body of the createNewThread method then it makes no sense. But if other stuff actually happens in createNewThread then there might be a good reason. The most common scenario for having a background thread use performSelectorOnMainThread: is if the UI needs to update as a result of the background activity. Like if you're processing a large data set and you want to show the user how much progress has been made so far. UIKit is not thread-safe so you can't update the UI from the background thread. But you might do something like, have the background doing a lot of work in a loop, and at every pass through the loop (or every 5, or whatever) call back to the main thread to update the UI. This makes the code switch back to the main loop just long enough to update the UI before returning to the background for the heavy duty work.

NSOperationQueue lag on IOS4

I wrote some sample code in a separate application, that basically queues up items in an NSMutableArray. I then have a method which loops through that array and creates an NSInvocationOperation, puts it in the NSOperationQueue, releases the operation and so forth. The method then gets called (simply prints out the string that was stored in the array and passed into the operation), does it's job, and sends an NSNotification back to the ViewController. The observer method gets hit, but the operations have a lag on them. For instance, the observer method simply updates a UILabel with how many messages are left in the queue. It eventually does this, but there seems to be a five second lag in between all of the NSOperations completing and the UI updating. To me it seems like the NSOperationQueue is blocking the main thread. Is there anyway to get the UI to respond immediately to the notifications?
One important note is that I have not tested this on the phone yet, just the simulator. I'm not sure if this makes a difference.
Sorry in advance. I'm away from my computer and I don't have the code in front of me. Hopefully I explained it well enough. Also I have read the documentation, just haven't found anything that's really answering this specific question for me.
The delay is typical of UI updates that are performed on threads other than main.
To see your update instantly on the UILabel, be sure to invoke whatever method is updating the label's text as follows:
[self performSelectorOnMainThread:#(myMethodToUpdateLabelWithText:) withObject:text waitUntilDone:NO];
where myMethodToUpdateLabelWithText is a method within your class that sets the label's text value.

Performing App Delegate method on main thread from secondary thread

I have a Iphone app with 2 threads. One is listening to the server, and the other is doing UIKit, OpenGl stuff.
I need to run a method that updates a view from the secondary thread thats listening to a server on the main thread that handles the views so I used
performSelectorOnMainThread:#selector"createGuessingView" withObject:nil waitUntilDone:YES
but for some reason, the method never gets executed. Putting a breakpoint or a printf at the beginning of the method shows that its never invoked. Im really stumped here. Ive used performselectoronmainthread in the same program to update text fields and it worked flawlessly.
edit:
Figured it out :)
The problem was that the object that I was using performSelectorOnMainThread was set by this thread before the object was initialized (even allocated) in the main thread. Therefore, the reference was pointing to null, and the selector was not getting recognized.
Thanks for the help
Shouldn't that be:
#selector(createGuessingView)
with no quotes.
--
EDIT (in response to comment)
What the signature for your method? If it's:
- (void)createGuessingView:(id)something
then you should remember the colon, as in #selector(createGuessingView:)