Load App after parserDidEndDocument - ios

I'm reading XML from internet in my AppDelegate inside didFinishLaunchingWithOptions, but the problem is my app got loaded before parserDidEndDocument got triggered!
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[self openXML];
NSLog(#"loaded?"); //target
[self.window addSubview:tabController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)parserDidEndDocument:(NSXMLParser *)parser{
NSLog(#"loaded.");
}
How can I hold loading the app until parserDidEndDocument triggered?
Moreover, how can I proceed & continue loading the app if I couldn't load the XML for any reason?

You are going to parse xml in app, so in any way you need to run and load you app at first :). So, if you need to perform some synchronious task in main thread then simply create an empty view with dark backround and UIActivityIndicator, bring this view to user without interactions( perhaps). When task will finished (parserDidEndDocument) just remove that view.

Related

"Application windows are expected to have a root view controller" message when adding view immediately after launch, iOS 9 only

My app sends a request at startup and displays a brief message to users when it succeeds, by means of MTStatusBarOverlay. Unfortunately, my current implementation seems to run afoul of iOS 9's view life cycle paradigms. I get the message
Application windows are expected to have a root view controller at the end of application launch
and the app crashes. The app works fine on iOS 7 & 8.
From searching around online, it seems like this might occur when trying to add the message view to the view hierarchy before the root view controller is established for the app's UIWindow, but that doesn't seem to be the case here, see below.
Here is an excerpt of the UIApplicationDelegate implementation:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[...]
self.window.rootViewController = [[MyViewController alloc] init];
[...]
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[MyDataManager sendRequestWithCompletion:^{
// Displays a message with MTStatusBarOverlay
[self showSuccessOverlay];
}];
}
application:didFinishLaunchingWithOptions: is called before applicationDidBecomeActive: so it seems like there should never be an issue with rootViewController being established.
Why is this happening? What's different about iOS 9 that's causing the app to break?
MTStatusBarOverlay is a subclass of UIWindow, so instantiating one during app launch adds that UIWindow to the list that iOS checks for a populated rootViewController when launch completes.
I was able to work around the issue by instantiating and assigning a dummy controller before using the overlay, like so:
[MTStatusBarOverlay sharedInstance].rootViewController = [UIViewController new];
[[MTStatusBarOverlay sharedInstance] postMessage:#"Message"];

Best way to get notification to rootViewController

I am looking for some advice as to the best way to handle this situation:
In my appDelegate I call registerForRemoteNotificationTypes in didFinishLaunchingWithOptions as follows:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Let the device know we want to receive push notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
[[self window] setBackgroundColor:[UIColor blackColor]];
[self.navigationController setNavigationBarHidden:YES];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
However, I need to wait for a device token to be returned before my app can continue, so I was wondering what the best place to wait for this before continuing? Currently my viewDidLoad gets called, but I sometimes have failures because the device token did not come back yet.
I was thinking that I could move my code from viewDidLoad to myViewDidLoad and was hoping I could wait for a notification that would happen once I receive the device token and then call myViewDidLoad.
But, I am not sure where to set the notification. I know this is a basic question, but I am still learning iOS.
Any suggestions would be most helpful.
You don't wait. Never, never wait.
When dealing with asynchronous stuff like networking (as here), you must write your app in such a way that it can proceed in some way even if the networking hasn't happened yet. It's that simple.
Your second impulse is much more correct. When you get the remote notification in the app delegate (I'm assuming), the app delegate can talk to the view controller in question and give it the new info and tell it to update itself (and the view controller can then update the view to display whatever needs displaying at that point).
Since you know you're going to need to do this, you need to set up "lines of sight" communication in advance. You have all the pieces of the puzzle in your hands in the app delegate, so you can arrange to hang on to a reference to that view controller, for when you'll need it later.
I posted a comment to my question with my solution. Not ideal, but it works for now.

Making launch image disappear faster

In order to make my app launch faster so I can start contacting with the server I made AppDelegate launch fast by cleaning all kind of work like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//[self redirectConsoleLogToDocumentFolder];
[[Ubertesters shared] initialize];
return YES;
}
What I want to achieve is loading my app faster to splash screen and show in the middle of the screen some kind of spinner (SVProgressHUD or UIActivityIndicatorView), so far I'm putting the spinner in the splash screen viewWillAppear.
This is what happens: didFinishLaunchingWithOptions load fast, then SplashScreen-viewDidLoad load fast and then viewWillAppear took a few seconds, but most of the way I see the image I set up as launch image and not my SplashScreen image with spinner animation.
Any ideas how can I make the launch image disappear faster and show my animation?

Every time my app launches (whether from cold launch or background) I want to have it do something, how do I accomplish this?

I want to check every time the app launches whether or not there's a URL in the clipboard, and if so, do something with it. Which method fires that I can override whenever the app launches, whether from a cold launch (it was killed in the background for instance) or if I just press the home button, copy a URL and jump back in.
Is it one of these?
- (void)applicationDidBecomeActive:(UIApplication *)application
- (void)applicationWillEnterForeground:(UIApplication *)application
- (void)applicationDidBecomeActive
- (void)applicationDidFinishLaunching:(UIApplication *)application
Confused.
As #rmaddy says, the correct method to use once the app launched is applicationWillEnterForeground: from your app delegate.
This method will be called when the user jump backs in, but NOT in other circumstances you don't need to respond to (such as the user receiving a text message and dismissing it).
However, from my testing, applicationWillEnterForeground: is not called when an app is launched from cold; you should catch that in applicationDidFinishLaunchingWithOptions:.
So, basically, your app delegate should include code like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self checkForURL];
...
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[self checkForURL];
...
}
- (void)checkForURL{
//code for checking for URL goes here
}
Hope that helps.
- (void)applicationDidBecomeActive is called when the app is launched or becomes active from the background.
This doc explains everything pretty well: http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
With reference to the UIApplicationDelegate Protocol, the handling of app launches can be handled in 2 methods:
application:willFinishLaunchingWithOptions:
application:didFinishLaunchingWithOptions:
And the handling of app launches from background can be handled with the help of method:
applicationDidBecomeActive:
Based on the above call, you can handle your application.
In your app delegate add it to the methods that the other answers have suggested (applicationDidFinishLaunchingWithOptions:). In your root view controller register for the following notification. This will always be called when your application launches once it has already started running.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(bringingItBack) name:UIApplicationWillEnterForegroundNotification object:nil];
This will cover both the instances when the app launches and when you are just bringing it back from the background.

How to display default image in iPhone App for long time?

Is it possible to display Default image which is shown when iPhone/iPad App starts for long time that what it usually does? Because in my app it varies sometimes that image is displayed for long time and some time is just flashes and it loads main app.
Sumit
Make the first view in your application show the same image as your Default image. You can even show it as a Modal and dismiss it with an animation or after a delay.
Yes you can use [NSThread sleepForTimeInterval:1.0];. Just change the 1.0 to what ever you want. But Apple might not approve your app if you make it stay up too long. It goes against the iOS Human Interface Guidelines.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add a 1 second delay
[NSThread sleepForTimeInterval:1.0];
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
[self.window addSubview:tabBarController.view];
return YES;
}

Resources