UIView's drawRect Calls When Backgrounded - objective-c

I am working a multitasking app which continues for a while after being sent to the background. I noticed that the drawRect methods in one of the UIView gets called constantly when the app is in the background. This drawRect method is responsible for updating the user interface while the app works.
What is the best practice for this? I don't want to be wasting CPU cycles drawing something that the user won't see.

Maybe the answer to this question might help you out:
Check if iOS app is in background
Check if the app is running in the background, and if so... don't draw anything.

Related

What may cause all UIView animations to finish instantly?

I have an iOS app where I use a lot of UIView animations. They'll all work perfectly for a very long time, then suddenly all animations finish instantly instead of using the specified duration. No errors and the app still functions, but the animations don't work properly.
The app will do a lot of downloading small graphic files in the background then call a selector on the main thread to present the graphics.
Does anyone know what may cause this kind of behavior?
I know it's not okay to handle UIKit in backgrounnd threads but thought it was limited to all drawing, like adding subviews etc. It seems creating and changing views (without adding them as subviews) is not okay either. My problem in particular was creating UIImageViews in a background thread. I changed the code to load into UIImages and create the UIImageViews in the presentation code, which is run in the main thread and now it's completely stable.

Can I build UIView elements on a separate thread?

I have an app that has to load and render a fair amount of content onto screen (mostly loading from a database).
I won't post all the code here but in effect it simply builds up a set of UIView objects that are added to a UIScrollView object. Nothing too complicated, just loaded quite a lot of stuff. This currently takes a second or so render everything (running on the main thread).
I want to show an activity indicator whilst the loading is happening, and I think the best way to do this is to have the method that takes a long time happen on a background thread and "report back" when it is complete.
The question is this. I know all the actual drawing is done by the main thread, so is it possible to create a new thread and have that build up a set of UIView objects that are then drawn on screen?
there is a great WWDC2012 session video, that deals exactly with your use case:
WWDC2012 Building Concurrent User Interfaces in iOS
Basically the trick is to prepare and draw the views on another queue and ship it over to the main queue.
You are correct. All the UI work should be done on the main thread. In your case I would suggest you to add the UIView object which are visible to the scrollview and add rest of them only when scrollview starts moving to that point. You can keep on adding views once they are about to be visible and remove any views which are not needed from the scrollview. This normally helps in better memory management.

Disabling buttons before view rotates

So been working on another app recently for iOS which incorporates a UIImagePickerViewController. App is ready to go and all works fine under normal circumstances, but if the user is being eratic and pushing buttons whilst rotating the iPad, then things go slightly awry and views load in the wrong place.
So basically, I want to disable all my buttons before the iPad is rotated and enable them again after the view is done rotating.
I thought this would be easy using the
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
and
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
methods.
But because the UIImagePickerController is being displayed, this for some reason stops these methods from being called. So I can't use these methods.
So basically, what I'm asking is if anybody can think of any other ways that I could achieve this??
Thanks,
Matt
You could subclass UIImagePickerController and then implement those methods on your UIImagePickerController subclass.

Core Graphics- drawRect: not getting called frequently enough

In my application, I have a UIViewController with a subclassed UIView (and several other elements) inside of it. Inside of the UIView, called DrawView, in my drawRect: method, I draw a table grid type thing, and plot an array of CGPoints on the grid. When the user taps on the screen, it calls touchesBegan:withEvent: and checks to find the closest point on the grid to the touch, adds a point to the array that the drawRect: method draws points from, and calls [self setNeedsDisplay]. As the user moves their finger around the screen, it checks to see if the point changed from the last location, and updates the point and calls [self setNeedsDisplay] as necessary.
This works great in the Simulator. However, when run on a real iPhone, it runs very slowly, when you move your finger around, it lags in drawing the dot. I have read that running calculations for where to place the points in a different thread can improve performance. Does anyone have experience with this that knows this for a fact? Any other suggestions to reduce lag?
Any other suggestions to reduce lag?
Yes. Don't use -drawRect:. It's a long and complicated reason why, but basically when UIKit sees that you've implemented -drawRect: in your UIView subclass, rendering goes through the really slow software-based rendering path. When you draw with CALayer objects and composite views, you can get hardware accelerated graphics, which can make your app FAR more performant.

progressView doesn't work

i want to show a progressView when the app is launching (with the splash screen) so, in the appDelegate .h file i declared a progressView :
UIProgressView *progView;
and in the appDelegate .m file i did this :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
sleep(1);
progView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
progView.progress = 0.75f;
// the rest..
}
i didn't see the progress bar in the splash screen, help please, thx in advance :)
You cannot influence the splash screen itself, it's only a static image.
What you can do however is to let your app load until you get the delegate message, then fire up some basic UI which shows your progress view and then do some heavy startup process in a background thread, updating your progress bar accordingly. When the thread has finished its work, call back to the main thread to start the real application.
Edit: Updated my answer to clarify some things
The application startup in iOS happens basically in 2 phases.
The operating system launches your application, the app sets up basic stuff, starts the run loop, etc. During this time the splash screen is shown. During this phase the application is not under the control of the programmer.
-application:didFinishLaunchingWithOptions is called. In this method you as a programmer may do some startup tasks, such as loading the database, connecting to some service, etc. During this phase you can influence the user interface and also show for example a progress bar. If you need to do this, create a background thread and do the setup work there.
Note: It does not work if you just put a progress bar on the UI and then do some stuff in the -application:didFinishLaunchingWithOptions: method, since the UI is not shown until after this method has returned. That's why you need to do the setup in a background thread.
is that all the code for progView? Cuz you haven't added it as a subview to anything, so how would you be able to see it? You need something like:
[splashView addSubview:progView];
frenetisch gave some reasonable explanation of the startup process of an IOS app, but it sounds like you need to do some basic investigation into this. It generally takes very little time before your didFinishLaunchingWithOptions is called and you can show your first view. But what things do you then need to do before your app is actually usable? You want to show a progress view so there must be SOMETHING that you plan to do that takes some time. It's while THAT is going on you need to show the progress view and somehow update it's progress.