CFRunLoopRunInMode freeze in IOS - iphone

Hello I have a problem with UITableView freeze,
"downloadItem" below gets called when someone clicks on a button on the iPad. Its supposed to download a file and then return.
During the download, while stuck in that function, I want the UI to still be responsive, so I installed a runloop like below.
The actual downloadItem function is WAY more complicated than shown below, but what is shown is the basic idea of it. I know this isn't the best way, but for other reasons, I can't change it at this time, especially due to the existing complexity of the actual function.
The problem is that I also have a UITableView on the screen (as well as the button), if the UITableView is clicked or scrolled while in this function, in the runloop, the UITableView sometimes freezes up, and remains frozen even after exiting this function. This doesn't happen every time for some reason, maybe 40% of the time.
Does anyone know how to fix, is the RunLoop call below done right? Why when I click on the UITableView while in the runloop below, the table sometimes freezes up?
-(IBAction) downloadItem
{
BOOL downloading=TRUE;
callFunctionsToStartdownload(...);
while (downloading) {
downloading=DownloadSomeBytes(...);
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, YES);
}
}
thanks

In general, this seems unnecessary. You want the processing of downloaded bytes to be in a thread (which this does not address), but the actual asynchronous NSURLConnection should do its work in a thread (and then calls back to the thread that started it).

Related

UITableView won't appear until a scrolling action

I have already made this kind of thing maybe one hundred times but, this time I'm so disturbed:
I have an UITableView with custom UITableViewCell which loads a picture via AFNetworking [-setImageWithURLRequest:]; and when I run the app, the content of the tableview doesn't appear.
If I wait, 8 seconds later, the content appears but if I made an interaction like scrolling, the content appears immediately. So strange.
I already tried to solve the issue with this article: http://blog.slaunchaman.com/2011/08/14/cocoa-touch-circumventing-uitableviewcell-redraw-issues-with-multithreading/ but without success.
Thank you.
Sounds like you are updating your table's contents off the main thread (UI thread), without seeing any code this would be my best guess.

Delegate Method only Firing after 5 or so Button Presses?

I'm having the most bizarre problem which I'm not even close to figuring out. I have a button which fires a delegate method. Once upon a time it was working fine, but after making some changes to my code, now the delegate method only fires after I push the button x amount of times (the changes I made to the code had nothing to do with the infrastructure that connects the delegate together). It varies, it can be 5 times to 10 times. I used the analyzer to check for memory leaks and there aren't any.
There is too much code for me to paste here (I don't even know where to start or where the problem could be), but I'm wondering if anyone has experienced this problem before, or what could be causing it? This is very odd and have no clue what could be causing it.
sounds like some other view is getting the touch events over the button. I've also seen this type of behavior when the touch area is too small (either because the button is too small or because it's getting clipped by another view)

UIActivityIndicator issues -- sometimes it doesn't stop

I have an activity indicator that is working fine. Most of the time. But sometimes it just keeps going. The code is pretty spread about, so I'll have to explain.
I'm doing a calculation. Sometimes it only needs updating, so it's fast. Sometimes it's lengthy, and may have to get new data from a server. When the calculation takes some time, the activity indicator works. When it's fast, though, the activity indicator will start, but not stop. Is there a minimum time for the animation? Has anyone else run into this?
I'll try writing something to gate the startAnimation based on the last time the calculation was done. Any suggestions?
UPDATE: OK. it' solved. Logging (as suggested) did show up that there was second call to startAnimating, leading to a race condition: sometimes the calculation was long enough that both calls arrived before the stop. I've now eliminated the second call and it's working!!
Are you sure that you call stopAnimating from the main thread? Changes in the UI have to be made on the main thread. Otherwise you will experience nothing at all, strange behavior or delays.
Put something like that NSLog before you call stopAnimating to make sure it is called at all and from the main thread.
NSLog(#"main thread? %#", [NSThread isMainThread] ? #"YES" : #"NO!");
Doing UI updates from another thread is often the reason for unexpected results, particularly for UIActivityIndicatorViews because they are usually used with threads.
My guess is that you call endAnimation before startAnimation or not at all. These are the most common causes for such problems...
Did you try NSLog when these two methods are called?
For these situations I like to build a sort of reference counted activity indicator. Basically every time you do something on the network, you increment the network activity count. Then when it's done you decrement. If it ever hits 0, you stop it. If it's above 0, you start it.

Objects not being released fast enough, causing an app relaunch crash

I have an app where I have 5 sets of animations that I'm storing in an array. The animations get picked to play randomly after a button touch. This is all working perfectly, however I noticed a bug when I quit the app and reopen immediately, I'll see my main view, then it'll jump to my second view that has the animation in it. (This shouldn't happen since you have to tap the main view in order for it to modally swap in the second view. If I interact with it everything works for a few seconds, then it closes with no crash log.
I finally realized that some of the objects must not be getting released fast enough, since if I close the app and wait three seconds, then reopen, everything executes fine.
I didn't want to put down code to show as this is more of a brainstorming question. I'd love any insight that could point me the right way. I changed a lot of my code to get rid of convenience methods and have all my variables defined and then released in my dealloc.
Is there a way to truly tell the app to kill everything on quit? It's not set to run in the background so this is a bit odd. Thanks for your help I'm still new to this and learning!
Alright, after working on this all weekend and doing more research comparing a barebones version of my app to my prerelease version, I traced memory leaks to the Flurry Analytics api that I am using. Apparently I was suffering from the same issue as the post here: App hangs on restart with latest Flurry SDK and ios4 . I resolved this by setting these optional methods to false, since they take extra time to send data after the app terminates, and depending on the connection it takes a few seconds.
FlurryAnalytics.h
/*
optional session settings that can be changed after start session
*/
+ (void)setSessionReportsOnCloseEnabled:(BOOL)sendSessionReportsOnClose; // default is YES
+ (void)setSessionReportsOnPauseEnabled:(BOOL)setSessionReportsOnPauseEnabled; // default is YES
Hope this helps anyone else who experienced something similar to me!
All apps can enter the background by default. Normally they do not do anything there, but they stay there in a frozen state and when you open them again, your program does not restart, it just picks up where it left off.
Anything that's set as an animation delegate might not get released, since it's retained for that purpose until the animation completes.
You can add an applicationDidEnterBackground: method to your app delegate to get informed when your app is going into the background, but exactly what you need to do depends on the design of your app. You can also add applicationWillEnterForeground: to do anything you need to do differently when restarting, as opposed to newly starting.
You might be able to force your animations to complete by starting a new animation with duration 0.0 (or very short if for some reason you can't do that).
If this happens only if your app goes to bkgnd and comes back AND you don't mind if the app restarts everytime it comes back then just put UIApplicationExitsOnSuspend in your app's plist. In all my cases where these and other bad things happen with apps going to and returning from bkgnd this helped.
While you might still see the app on the buttom when double tapping it is really stopped and will restart. Apps that show on the buttom do not always have to run or be stored in the bkgnd I learned.
ps. don't forget to set the value of UIApplicationExitsOnSuspend to YES

How do I prevent reloadRowsAtIndexPaths to block the user input?

I have implemented a client for a paginated REST service where I populate the whole table with empty entries and then load them in the background using pagination when the user starts scrolling the table.
This seems to work very well except for a little detail: I am calling reloadRowsAtIndexPaths: in the main UI thread (because UIKit requires so), and I feel the animation sometimes makes me lose input touches.
This is, the user starts scrolling through the list and items start to load. Sometimes a reload animation happens at the same time the user is just touching the screen again, and this touch is not recognized. The scrolling then doesn't continue and stops. It doesn't happen all the time, and I guess it is an infrequent user case (the user is expected to read each row of results before scrolling down) but it annoys me to no end.
I'm doing most of my animations with blocks and the flag UIViewAnimationOptionAllowUserInteraction is really helpful, so is there a block version of reloadRowsAtIndexPaths where the reload animation would not block the user interaction with the scrolling?
I think the solution you seek is to background-load your data in a thread (as you describe) and only call reloadRowsAtIndexPaths: once the data is received and ready to display. You should also probably redisplay the data NOT animated.
I don't think there's anything you can do to get around the missed touches with your current scheme. My suggestion is to "do what iOS wants" rather than "try to cajole iOS to do what you want." Yes, probably not the answer you wanted to hear, but I think that's just the way it works.
(Btw, you can always use bugreporter.apple.com to make an enhancement request! :)