A function called from different class does not work properly - objective-c

I have a tabbar iPhone application in which tabbar is the root controller and each of the tabs is launching a separate webview window. Each time user taps one of the tabs I intercept the tap in AppDelegate and perform actions, one of which is displaying loading screen (an image in the tabbar view, with display toggled TRUE/FALSE).
My problem is, the loading screen is only displayed when all operations in AppDelegate are finished, which pretty much defeats the purpose of it. My guess is that I did some fundamental error designing this solution, but being a very inexperienced in iPhone programing I don't know how to fix it.
I'm accessing the function showLoading through iboutlets defined in AppDelegate:
[hv showLoading];
And this is what it does:
- (void) showLoading
{
loadingView.hidden = FALSE;
wheelHome.hidden = FALSE;
[wheelHome startAnimating];
NSLog(#"showLoad 1");
}
I'm seeing the "showLoad 1" immediately after bar is tapped, but loading image is only displayed when didSelectViewController exits.
My question - how can I make loading screen appear from AppDelegate OR is there a better way to display loading screen?

The problem is, that the UI is only updated when the event handling code returns to the run loop. You have two options:
Prepare for your long-running task (setup the UI) and then start the task by [myDownloader persormSelector:#selector(download) withObject:nil afterDelay:0];. The benefit of using performSelector:withObject:afterDelay: is that your code returns to the run loop, gets time to update the UI, and then immediately starts the task.
Design your long running tasks (downloading, ...) so that they perform in the background.

First of all, your tabbar should be controller by a UITabBarController and not the app delegate. See the Xcode TabBar template for implementation details.
Secondly, it sounds like you want an Application Startup Image. That is a static image that works like a splash screen if you app takes a little while to startup.

Related

UIAlert during splashcreen

This is a two part question.
I have created a user agreement that the user must agree to when first launching the app (it is an alert with some information and agree/ do not agree button)
I call upon the method that creates this alert inside myAppDelegate.m and within the method
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
The problem is the alert pops up when the splash screen has finished loading and my first view comes up. I want this to happen during the splash screen. How would I do this?
The second question is When the users presses the "Do not agree button", I want them to exit the app so I have programmed it with
exit(0);
Is there a better way and will apple reject my app because of this?
Thanks in advance
1) You can't -- during the splash screen (your default.png) the app is loading into memory, and it cannot therefore execute any code, including presentation of a UIAlertView. That's why you don't see the alert until the splash disappears -- removal of the splash screen is the last thing that the app does before calling applicationDidFinishLoading:withOptions:.
What you can do is create a view controller that mimics your splash screen. This is easy -- you can even reuse default.png as a background if you want, though a better idea is just to present in this first view controller your agreement text and agree/disagree buttons.
As to your question re: use of exit(), it's best to avoid doing that. If the user refuses, you can simply do nothing. Of course, if you go the view controller route as I suggest, you can leave presented another opportunity for the user to agree.
Another thought is that Apple allows you to customize the EULA of your app when you upload a binary -- you could put it there and be covered.
Why not load our default.png as the background of you initial view and just handle the Alert in it's controller. you can always add another view or segue based on the answer.
The problem is the UIAlert blocks the Main thread, so it could stop your app from launching in time, and the process could be terminated.

Catch touch events anywhere onscreen in certain views?

I have a menu which I'd like to have automatically hide if it's inactive after a certain amount of time. This menu is composed of a hierarchy of UIViewControllers, which present various different views.
I'm thinking along the lines of running a timer, which invalidates and starts over whenever there's a touch.
Is it possible to catch all touch events in a set of UIViews? Perhaps just keep a boolean lying around and use the main UIWindow to catch touch events?
EDIT:
My app is a kiosk app of sorts, with a main screen and a menu. When the menu is up, I want it to run an auto dismiss timer, which resets after any touch in the entire menu screen. The menu is displayed over the entire screen, modally.
One way to be sure is to subclass UIApplication and override - (void)sendEvent:(UIEvent *)event method, every touch event happening in your app goes through this method and you can check the UIEvent type to see if it's UIEventTypeTouches and reset the timer.
Another way to do this simply involves adding a transparent layer over whole user accesible UI and override hitTest:withEvent:.
You can have an invisible view on top of your modals view controllers, and put have either a gesture recognizer on it which can start a timer, either a
-touchesBegan:withTouches
method, and then send to the .nextResponder the same method.

ViewDidAppear iOS 4.3 vs iOS 5, loading screen won't appear in 4.3

I have a rather annoying problem. I have a table view with blog entries (collected from a RSS feed). When the view loads, I apply a loading screen to the blogViews view via -addSubview:. And in -viewDidAppear: I start to load the data. This works and all with the iOS 5 simulator and on my iPhone 4 with iOS 5.0.1.
But when I do it on the 4.3 simulator, the loading screen doesn't appear. The screen is locked on the previous screen (another tableView) until the load is finished.
The problem is, of course, the loading shouldn't start until the view has appeared. To exemplify: When I click the tab bar button to open the blog, the load starts (which is in -vievDidAppear:), and when the load is finished, the screen appears - it should be the other way around! This is weird, why does it do it like that on 4.3 and not 5?
Should I use -viewWillUnload method in the first table View and apply a loading Screen? That means that there will always be a loading screen (for a flash of a second) when I unload it when there is no need of a loading screen.
(By loading screen I mean an UIImageView initiated with an image, and an activityIndicator on top)
Thanks for any input!
As Mark points out, your problem is related to blocking the main thread while performing a long operation that should in fact be performed on the background.
If you do so, it shouldn't matter when viewDidAppear: is called, since you won't be blocking the main thread while performing the loading.
You could solve this performing your loading operation on the background and then going back to the main thread to remove the loading indicator. You can do it easily with GCD:
- (void)viewDidAppear:(BOOL)animated
{
// ...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
// Perform your time consuming operation, eg. load your blog entry
dispatch_async(dispatch_get_main_queue(), ^{
// remove the loading screen and set your blog's data to UI components
});
});
}

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.

Cocoa Touch - Alternative to viewDidLoad Method

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.