Can I load Nib's in another thread? (iPhone dev) - iphone

At the moment, I'm getting data for the next view from the server.
While this goes on, I am showing the user a loading indicator.
After the data have been loaded, the main thread gets notified and loads the nib for the new view.
My question is:
Because I already have this loading mechanism, can I safely load the nib's in the working thread and just push them from within the main thread?

UIKit is not thread safe, so I suspect it should be pretty unsafe loading the nib in a secondary thread. Just loading the nib in a UIViewController and displaying it from the main thread could work for you and may break elsewhere.
I suppose you know about performSelectorOnMainThread:withObject:waitUntilDone to dispatch a method from a secondary thread to the main thread. You could try and use this from your secondary thread when you want to load the nib.
EDIT:
what about preloading the nib while the working thread is retrieving the data, so that when the working thread has done, the main thread has only to display the nib views?

Related

Main thread doesn't respond while NSOperationQueue is running its task

I use NSOperationQueue to create UIImages in the background,
upon image creation, main thread gets notified and set the image to a view.
While it works and all, main thread is not responding as I hoped while the NSOperationQueue is working.
The point of using thread here is to let UI be responsive to user interactions.
Am I missing something here?
check Invoking thread with a single parameter

(iphone) what shouldn't be done in background thread with respect to UIView?

I know and heard most UI related shouldn't be done in thread other than main.
I also know that you can update non-view related data member(that you added) of UIView derived class.
I wonder if the below operations are fine or not to do in background thread.
allocing UIView
init UIView with/without(CGRectZero or just init) frame info
modifying frame/image(UIImageView's) property of UIView
modifying image property of NSObject derived class. (treating UIImage as data)
accessing subviews with subviews method
etc.. Is there a well defined documentation on this issue?
Thank you
You shouldn't be doing anything view related in a background thread. All of the items you listed should not be done in a background thread. If you're breaking your app up correctly for MVC, the view should only contain items that dictate how it is displayed. So anything relating to one should only be in the main thread.
All of your data manipulation should be residing in your model. It can be threaded as needed for performance. Just be careful that you send any messages to update the UI for the data manipulation on the main thread. This includes notifications. They gets sent on the same thread they were created on. So it's easy to forget to switch into mainThread when sending one.

UIView takes too long to update

In an iPad app, I have a bunch of UIImageViews inside a bigger UIView. Each UIImageView contains a thumbnail that is generated in a separate thread (so as not to freeze the application). After thumbnail has been successfully generated I call setNeedsDisplay on main thread, however, it doesn't update the UIImageViews as the thumbs become available (I can see them in the log), rather it takes about 5 seconds and then displays all of them at once.
here's what I am doing when a thumbnail has been created in a separate thread:
[self performSelectorOnMainThread:#selector(setNeedsDisplay)
withObject:nil
waitUntilDone:NO];
any ideas?
What's your main thread up to? If your application waits until all the thumbnails are available before redrawing, then it sounds like maybe you are inadvertently blocking on your main thread until your thumbnailing queue has emptied. How are you setting up the threads?
The problem is that you can't tell cocoa that it have to redraw "now".
With setNeedsDisplay you can onely order a redraw, because drawing is ra rather expensive procces.
setNeedsDisplay
You can use this method or the
setNeedsDisplayInRect: to notify the
system that your view’s contents need
to be redrawn. This method makes a
note of the request and returns
immediately. The view is not actually
redrawn until the next drawing cycle,
at which point all invalidated views
are updated.
Mybe its a better and more performant solution to wait for all generated thumbnials?!
I would use NSNotification. Send a notification from your thread loading the images when an image is ready. Your view controller can observe these notifications and update the view as they arrive.

NSMagedObjectContext, threads and NSFechedResultsController

Core Data newbie speaking here.
In my application I have two NSManagedObjectContext that refer to that same NSPersistentStorageController.
One ManagedObjectContext (c1) is in the main thread --created when I create a NSFetchedResultsController -- and the second ManagedObjectContext (c2) created in a second thread, running in the background, detached from the main thread.
In the background thread I pull some data off a website and insert the entities created for the pulled data in the thread's ManagedObjectContext (c2).
In the meanwhile, the main thread sits doing nothing and displaying a UITableView whose data do be display should be provided by the NSFetchedResultsController.
When the background thread has finished pulling the data and inserting entities in c2, c2 saves, and the background thread notifies the main thread that the processing has finished before it exiting.
As a matter of fact, the entities that I have inserted in c2 are know by c1 because it can ask it about one particular entity with [c1 existingObjectWithID:ObjectID error:&error];
I would expect at this point, if I call on my tableview reloadData to see some rows showing up with the data I pulled from the web in the background thread thanks to the NSFetchedResults controller which should react to the modifications of its ManagedObjectContext (c1).
But nothing is happening! Only if I restart the application I see what I have previously pulled from the web!
Where am I doing things wrong?
Thank you in advance!
Reloading the table will not refetch items from the persistent store as you are expecting. Reloading the table is a "UI" level action and fetching data is at the model level. While this is fine for any changes that occur in the main NSManagedObjectContext, this will not cause the main NSManagedObjectContext to become aware of changes that occurred in another NSManagedObjectContext.
Depending on your design you need to do one of the following:
When the main thread receives the notification on the background thread's save it needs to call -mergeChangesFromContextDidSaveNotification:.
When this is complete you need to save the main NSManagedObjectContext
During the save it will trigger your NSFetchedResultsController with changes
The NSFetchedResultsController will notify its delegate (normally your view controller) of the changes and give you an opportunity to update the table view.
I suspect that you are not doing one of those items and thus breaking the chain of events.
Example
There is a solid example of multi-thread notifications in my article over on the MDN. If you are not familiar with the MDN, I highly suggest taking a look.

Loading a view on a background thread

Is it possible to load a view on a background thread?
I am using buffering to render views into a buffer off screen so they can be scrolled into view later. I want to make the UI more response and it seems to be the off screen buffering that is the culprit, and am wondering if I can load up the buffered view on a background thread as I don't need it available immediately. The problem with doing this seems to be that the thread has its own auto release pool, which then gets cleared when the thread exits. Is it possible for the background thread and the ui thread to share memory or a pool?
Secondary thread should have it's own autorelease pool. Which should be released if the secondary thread exists.
When you pass data between threads the sender should retain it and the receiver thread should release/autorelease it. But in most cases this is done "automatically", if you're using properties or performSelectorOnMainThread for example.