I'm writing a tab-based universal app where one of the tabs takes considerably much longer to load than the rest (approximately 5s), and it locks down the main thread while doing it.
Now, this specific tab is an image gallery, so it could be expected to take a little while to load and display the images, however, the delay occurs before I instantiate any of my variables... (The image loading is done on a separate thread anyway...)
I create my subviews etc. in the viewDidLoad method, but the delay occurs somewhere after the init method and before the viewDidLoad method.
(The delay is present even if I comment out everything in the viewDidLoad method.)
The View Controller is initialized with a nib containing nothing but a UIScrollView and a UIImagePickerController...
Does anyone know what's being loaded/processed before the viewDidLoad method?
This is a problem with loading UIImagePickerController on the phone while being attached to the xcode harness. This creates a longer than normal delay. Try testing on the device without being connected to the xcode debugger.
Related
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.
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.
I'm trying to load a window's size and other properties on application start. Unfortunately, if i do it on
applicationDidFinishLaunching
or
applicationWillFinishLaunching
... i get an ugly flicker, showing the unmodified window and quickly switching to a modified one. I know how to do this for my non-main windows that run with window controllers (usually i do this in awake from nib event), but how would i do it in an application delegate?
Thank you
You can tell the window to not be visible at launch, which means you can create your window, mess with its frame size and all that, and then show it.
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.
I am creating an app that reads a text file from the web. WHen the app first runs, I want a splash page to be presented with a logo. I have a SplashViewController and a MainController. I am using some code from a tutorial that allows you to add a subview to the MainController's applicationDidFinishLaunching method and replace the main controller's view with the splash screen (follow so far? Trying my best to explain)
The issue I am having is that I want the splash screen to be present until the data is loaded from the web and animate an activity indicator. However, I am retrieving the data from within the viewDidLoad method in the MainController and the app starts retrieving the data before the splash screen loads so there is a delay before the user sees anything.
Is there another method that I can use to begin the retrieval process after the splash has been displayed?
Have you tried -viewDidAppear: instead of -viewDidLoad:? The former is sent when the view has been added to the window whilst the latter is sent when the view has been loaded (from a nib file), i.e., hasn’t been shown yet.