NSThread Error - iphone

I have two uiviewcontrollers. I am using NSThread in first viewcontroller and its works perfect.. Some times the thread was running in the firstviewcontroller, that time i Want to go Secondviewcontroller.This action stops my thread of firstviewcontrollr..
How could i fix this... Can anyone help me?
Thanks in advance

It would be good if you could clarify the question, because it's hard to understand exactly what you want to do and what the problem is. In general, UI code should always run in the main thread. That is clearly stated in the Cocoa documentation, and you will not succeed in having several threads trying to control the UI.
If you want to run code in other threads and have them influence the UI, you need to implement mechanisms to communicate information to the main thread. One method that comes in handy is NSObject's
performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
If you want to use notifications, you must dispatch them on the main thread also. It is easy to get confusing bugs if you don't stick to this principle (although things might seems to work at first).

Related

sleepForTimeInterval change interval

I use sleepForTimeInterval. My code
- (void)runningInBackground
{
while (1) {
[NSThread sleepForTimeInterval:waitInterval];
[self getInterval];
}
}
How can i change interval if sleepForTimeInterval is not finished?
You can not. No run loop processing occurs while the thread is blocked.
There are almost no cases where sleepForTimeInterval: is correct iOS code. iOS performs these kinds of things with NSTimer, NSOperation or GCD queues. If you find yourself calling NSThread, you are almost certainly in the wrong part of the framework.
Without knowing the details of your problem, the tool you probably want is an NSTimer. They're simple to use, and solving this kind of problem is easy with them. You just invalidate the timer and create a new one when you want to change the interval. You don't need to break out of a sleep.
But you should always ask yourself if you could turn a polling (interval-based) solution into an event-driven solution. What are you doing when you wake up? If you're usually just checking something and going back to sleep, that's very bad for the battery. iOS has good solutions for making those things event driven in most cases (so you just get called when the thing you want occurs without polling).

UI blocked while NSFetchedResultsController loading data

I managed UITableView via NSFetchedResultsController, but all UI blocked(I can do nothing such as tap, scroll...) while NSFetchedResultsController loading data. Is there any solution to resolve this? Thanks!!!
One thing that is important to remember when making your application user friendly is:
If you have any intensive, non-UI related computations on the Main
Thread, you are doing something wrong!
Making the Main Thread UI only will make sure that the UI will never freeze, or as you describe it, get "blocked". Therefore, your NSFetchedResultsController should be on another thread, to ensure that this doesn't happen.
NSOperation's is definitely the way to go for the problem you are describing. Here is a tutorial and sample code which will explain a similar scenario, and how to fix it up.
Hope that Helps!

When is a Cocoa callback given controll?

I've been searching around the web for an answer to this one, but was unable to find an answer, on the other side I think it's something quite common thus there is a possibility I'm missing some keywords here. Anyhow, the problem is as follows:
When is control given to a callback function in ObjC (iPhone)?
Does it happen after control is given to a high up in the hierarchy class responsible for the runloop? Can it occur in the middle of another function call being executed?
As an example, let's take the NSURLConnection, we don't know or can't predict when it's going to call didReceiveResponse or the other callback methods, can it be the case that didReceiveResponse get's called when I'm in the middle of another function? (highly doubt that but was unable to find information on callbacks wating for the end of the run loop)
Cheers,
Kaspa
can it be the case that
didReceiveResponse get's called when
I'm in the middle of another function?
No, within a single thread, code is not executed in parallel. The runloop schedules the execution of all messages and dispatches them in sequences. Not even NSTimers are guaranteed to fire to the precision they are theoretically capable of because they have to wait for the runloop like everything else.
The callbacks will not be called from in a middle of your function, indeed. You have to give back control to the main runloop for it to process events, and call your callback.
If you want to know who exactly calls your callback, put a breakpoint in it, and check the stack trace.
The only time the didReceiveReponse will be called while something else is executing, is if you have launched the connection on it's own thread (typically in an NSOperation).
This is why when you do have connections in a background thread, you usually use something like performSelectorInMainThread to change the value for other parts of the application - though you can adjust properties directly if they are not marked nonatomic and are not mutable collections.
By default, basically all cocoa touch classes work entirely in a single thread, including many asynchronous operations like background network calls. The main exceptions are NSOperation and friends, and things related to NSThread.
The OS can do this by inserting its callbacks in the run loop schedule. There are also a few cases when one of your calls will also result in a callback on the same stack - for example, if you call resignFirstResponder on an object that notifies its delegate when this happens, such as UITextField.
A couple relevant blog posts:
quick intro to NSRunLoop
Friendly overview of Objective-C callbacks

NSThread and UIViewController interaction

If I spawn a new thread, and then within it I push a new controller onto my UINavigationController, using code like this...
(a) not working
-(void)myCallbackInThread
{
// move on...
UIApplication* app = [UIApplication sharedApplication];
[app changeView];
}
then I find that the view appears, but does not respond to user input.
If I change the code like this
(b) working
-(void)myCallbackInThread
{
// move on...
UIApplication* app = [UIApplication sharedApplication];
[app performSelectorOnMainThread:#selector(moveToMain) withObject:nil waitUntilDone:FALSE];
}
Then everything works just fine.
Any hints as to why?
In your case, it really depends on what's happening in [app changeView], but the reason it stops responding is most likely that you have no run loop dispatching events on your new, secondary thread (more on this below). In general, however, it is a very bad idea to update the GUI from a secondary thread. As you've already discovered, all of these events should go through the main thread.
The main reason that your second example works and not your first is that UIApplication sets up and handles the run loop and event dispatcher for you on the main thread. So, when you call performSelectorInMainThread, the selector gets dispatched to the main run loop which is able to then handle your gui input and other events. The event dispatcher is also run and managed by UIApplication on the main thread.
So basically, don't perform any GUI management activities on a secondary thread. Dispatch those to the main thread. And if you need processing on a secondary thread (for things like timers or asynch calls, etc.) then you have to start and manage your own run loop on that thread (see NSRunLoop for more on managing your on run loop).
Just found this in the iPhone threading docs
If your application has a graphical
user interface, it is recommended that
you receive user-related events and
initiate interface updates from your
application’s main thread. This
approach helps avoid synchronization
issues associated with handling user
events and drawing window content.
Some frameworks, such as Cocoa,
generally require this behavior, but
it also has the advantage of
simplifying the logic for managing
your user interface.
I still don't see what would actually cause something to display but not be able to receive user input, but I'll follow that guideline in future.
As the documentation says, "If you’re not sure about a particular graphical operation, plan on doing it from your main thread."
A good rule of thumb to follow is that, if a class isn't explicitly documented as being thread-safe, then it's probably not. Additionally, code that's not documented as being thread-safe may not fail fast when used by multiple threads, but may simply exhibit undefined behavior, as you saw.
Almost none of the UI code in UIKit or AppKit is threadsafe. How it fails is irrelevent, because if you are worrying about how it fails you are doing something that is going to result in all sorts of weird bugs that will subtly change between different OS release anyway.
My best advice is to not use things from background threads unless the docs say it is safe.

Using Core Graphics/ Cocoa, can you draw to a bitmap context from a background thread?

I'm drawing offscreen to a CGContext created using CGBitmapContextCreate, then later generating a CGImage from it with CGBitmapContextCreateImage and drawing that onto my view in drawRect (I'm also drawing some other stuff on top of that - this is an exercise in isolating different levels of variability and complexity).
This all works fine when it's all running on the main thread. However one of the motivations for splitting this out this way was so that the offscreen part could be run on a background thread (which I had thought should be ok since it's not rendering to an onscreen context).
However, when I do this the resulting image is empty! I've checked over the code, and placed judicious NSLog's to verify that everything is happening in the right order.
My next step is to boil this down to the simplest code that reproduces the issue (or find some silly thing I'm missing and fix it) - at which point I'd have some code to post here if necessary. But I first wanted to check here that I'm not going down the wrong path with this. I couldn't find anything in my travels around the googlesphere that sheds light either way - but a friend did mention that he ran into a similar issue while trying to resize images in a background thread - suggesting there may be some general limitation here.
[edit]
Thanks for the responses so far. If nothing else they have told me that at least I'm not alone in not having an answer for this - which was part of what I wanted to find out. At this point I'm going to put the extra work into getting the simplest possible example and may come back with some code or more information. In the meantime keep any ideas coming :-)
One point to bring up: A couple of people have used the term thread safety with respect to APIs. It should be noted that there are two types of thread safety in this context:
Threadability of the API itself - ie can it be used at all from more than one thread (global state and other re-entrancy issues such as C's strtok are common reasons that an API might not be thread safe too).
Atomicity of individual operations - can multiple threads interact with the same objects and resources through API without application level locking?
I suspect that mention so far has been of the first type, but would appreciate if you could clarify.
[edit2 - solved!]
Ok, I got it all working. Executive summary is that the problem was with me, rather than bitmap contexts themselves.
In my background thread, just before I drew into the bitmap context, I was doing some preparation on some other objects. It turns out that, indirectly, the calls to those other objects where leading to setNeedsDisplay being called on some views!
By separating the part that did that out to the main thread it now all works perfectly.
So for anyone who hits this question wondering if they can draw to a bitmap context on a background thread, the answer is you can (with the caveats that have been presented here and in the answers).
Thanks all
Just a guess, but if you are trying to call setNeedsDisplay from another thread, you need to call it via performSelectorOnMainThread instead.
What you're doing should work if you're working with the CGContextRef in one and only one thread. I've done this before with 8 cores working on 8 different parts of an image and then compositing the different resultant CGImageRefs together and drawing them onscreen.
Apple don't say anything about thread safety on iPhone but Cocoa (as opposed to UIKit) is generally thread safe for drawing. As they share a lot of drawing code, I would assume drawing on iPhone is threadsafe.
That said, your experience would imply there are problems. Could it be that you are using your image before it is rendered?
Not all APIs are thread-safe. Some require locking or require that they be run on the main thread. You may want to scour the documentation. I believe there is a page that summarizes which parts of the SDK are thread-safe and which aren't.
In case anyone is/was searching for exactly how to do this i've written a blog post that describes how to do this, and wraps the whole thing in a NSOperation subclass.