I am having a Default.png file in my project, so that whenever my app launches Default.png file loads there. As my app is retrieving data from server at startup(app launch), i want to show activity indicator as well while Default.png file is loading. Is it possible to activate both the process at a time, i mean showing Default.png and enable activity indicator at a time during startup?
But i tried putting Activity Indicator code in 'applicationDidFinishLaunching' but it doesn't show activity indicator at the time of showing Default.png file. But i am sure that Activity code what i have, is working fine on other screens. Problem is only during app launch.
Can someone share your ideas please?
thanks.
Clave/
You can't do any animation in the Default.png image. You should replace it as soon as possible with a view/controller (containing the activity indicator). Than after showing that controller, load your data and possibly an other controller (in a thread).
What i do in my app is immediately load an imageview with the Default.png image covering the screen. then you can add a progress indicator on top of the imageview while you do your server work on a background thread.
You should always avoid net activity in the applicationDidLaunch method as this method has a timeout after which, if it does not return, Apple will kill your app. this is important because say the user is on edge and the server trip takes 30 seconds - your app will appear to have crashed to the user.
By doing the net work in a background thread and returning applicationDidLaunch, you will keep apple from killing your app, you will be able to let the user use the app before the new data comes in (if you want) and your app will appear to launch faster.
You should always avoid net activity in the applicationDidLaunch method as this method has a timeout after which, if it does not return, Apple will kill your app. this is important because say the user is on edge and the server trip takes 30 seconds - your app will appear to have crashed to the user.
So you think that I should not put XMLPraser on the applicationDidLaunch?
NSURL *url = [[NSURL alloc] initWithString:#"http://sites.google.com/site/iphonesdktutorials/xml/Books.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
//Initialize the delegate.
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
That's how it works:
(Made on Xcode version 4.2.1)
So...
In the AppDelegate.h add this:
#property (nonatomic, strong) UIImageView *splashView;
In the AppDelegate.m add this:
On the top of the page of cours #synthesize splashView;
And then:
- (void) splashFade
{
splashView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0, 320, 480)];
splashView.image = [UIImage imageNamed:#"Default.png"];
[_window addSubview:splashView];
[_window bringSubviewToFront:splashView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0];
[UIView setAnimationDelay:2.5];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:_window cache:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(startupAnimationDone:finished:context:)];
splashView.alpha = 0.0;
[UIView commitAnimations];
//Create and add the Activity Indicator to splashView
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityIndicator.alpha = 1.0;
activityIndicator.center = CGPointMake(160, 360);
activityIndicator.hidesWhenStopped = NO;
[splashView addSubview:activityIndicator];
[activityIndicator startAnimating];
}
- (void)startupAnimationDone:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
[splashView removeFromSuperview];
}
The [UIView setAnimationDelay:2.5] is responsible for how long the splashView will be in front by the delay time you choose.
You can change the position of the indicator by changing the nubmers of x/y in:
activityIndicator.center = CGPointMake(160, 360);
At last, under the methode:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Just add this:
[self performSelector:#selector(splashFade) withObject:nil];
And there you go :)
Hope it helped.
Have a nice programming....
Related
When launching an iOS application, the screen jumps from the Default.png into the interface. For a current project, I'd like to fade in from that Default.png into the app's interface. Is there a good way to do this?
I took a bit of rooster117 and runmad's answers, and this is what I came up with.
Add a UIImageView to the first UIViewController's properties:
#interface DDViewController : UIViewController {
...
UIImageView *coverImageView;
}
...
#property (nonatomic, retain) UIImageView *coverImageView;
Then, for the "home screen" of the iPad app, I call the following:
- (void)viewDidLoad
{
[super viewDidLoad];
...
coverImageView = [[UIImageView alloc] init];
}
-(void)viewWillAppear:(BOOL)animated {
UIImage *defaultImage;
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
NSLog(#"Landscape!");
defaultImage = [UIImage imageNamed:#"Default-Landscape.png"];
} else {
NSLog(#"Portrait!");
defaultImage = [UIImage imageNamed:#"Default-Portrait.png"];
}
coverImageView = [[UIImageView alloc] initWithImage:defaultImage];
[self.view addSubview:coverImageView];
}
-(void)viewDidAppear:(BOOL)animated {
//Remove the coverview with an animation
[UIView animateWithDuration:1.0f animations:^(void) {
[self.coverImageView setAlpha:0.0];
} completion:^(BOOL finished){
[coverImageView removeFromSuperview];
}];
}
Yeah this isn't that hard to do. I accomplish this by making an image view with the default image and just animating it out. Something like this (put in the viewDidLoad of the first view controller):
_coverImage = [UIImage imageNamed:#"Default.png"];
}
[self.view addSubview:_coverImage];
[UIView beginAnimations:#"FadeOutCover" context:nil];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(removeAndDeleteCover)];
[_coverImage setAlpha:0.0f];
[UIView commitAnimations];
then implement removeAndDeleteCover and do:
[_coverImage removeFromSuperview];
Hope that helps and if you need it to work for the iPad as a universal app you will have to check for that case and add the right default image.
Someone made a control for it on cocoacontrols.com
Here is the link for it: http://cocoacontrols.com/platforms/ios/controls/launchimagetransition
Expanding on rooster117's answer, you'll want to properly load your final "landing place", that is the view controller you want the user to actually interact with, before dismissing the "splash screen" view controller. This is very important for apps that load data from the network.
I seem to have done this in ios7 this way, think it should also work with 6 ?
https://stackoverflow.com/a/19377199/1734878
I am using ARC in my app.
Now I faced a real problem. I need to animate two view controllers from left to right. So I just animate the the two views in button action like,
// thanks to stackoverflow for this code
test *control = [[test alloc] initWithNibName: #"test" bundle: nil];
control.view.frame = self.view.frame;
control.view.center = CGPointMake(self.view.center.x + CGRectGetWidth(self.view.frame), self.view.center.y);
[self.view.superview addSubview: control.view];
// Animate the push
[UIView beginAnimations: nil context: NULL];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: #selector(pushAnimationDidStop:finished:context:)];
control.view.center = self.view.center;
self.view.center = CGPointMake(self.view.center.x - CGRectGetWidth(self.view.frame), self.view.center.y);
[UIView commitAnimations];
- (void) pushAnimationDidStop: (NSString *) animationID finished: (NSNumber *) finished context: (void *) context
{
[self.view removeFromSuperview];
}
and in the second view controller I did the same but change the animation direction.
My real problem is when I run this code, every time I create an object of the another class and it is not deallocating. By profiling this code, found that the every time the object is alive and it is not dying and the memory allocation get increasing.
You can run the allocation instrument with reference count recording enabled. Then evaluate where the offset differs from your expectations, based on that data.
I have been working three days straight to try and integrate ads into my iPhone game. I chose mobfox and it's been going well except a minor detail that is directly linked to my less than appropriate level of Objective-C skills.
I have everything working except that the ads get's obscured by a UI element. So I want to bring the ads to the front and googled around and managed to figure out this:
[self.view bringSubviewToFront:bannerView];
However, that only works once as the code is in (void)viewDidLoad. I then tried to use the same code in other places of my code, in the UI init etc but I then get an error that the bannerView is not declared. I pretty much understand what xcode is telling me but I don't have the skills to simply declare it and be done, I don't know how to so I ask if you can help me?
All I want to do is to bring my bannerView to front at will from anywhere in the code.
Can you help me?
Best regards
Marcus
Below is the mobfox code
The following is in viewDidLoad
// MOBFOX Starts
// create the banner view just outside of the visible area
MobFoxBannerView *bannerView = [[MobFoxBannerView alloc] initWithFrame:
CGRectMake(-800, self.view.bounds.size.height - 240, 320, 50)];
bannerView.delegate = self; // triggers ad loading
//bannerView.backgroundColor = [UIColor darkGrayColor]; // fill horizontally
bannerView.transform = CGAffineTransformMakeRotation(M_PI / 2.0); //MARCUS haxx
//bannerView.refreshAnimation = UIViewAnimationTransitionCurlDown;
[self.view addSubview:bannerView];
[self.view bringSubviewToFront:bannerView];
NSLog(#"MobFox: Ad initated and placed offscreen");
//
This is directly after viewDidLoad
//MOBFOX STARTS HERE
#pragma mark MobFox Delegate
- (NSString *)publisherIdForMobFoxBannerView:(MobFoxBannerView *)banner
{
return kMyMobFoxPublisherId;
}
- (void)mobfoxBannerViewDidLoadMobFoxAd:(MobFoxBannerView *)banner
{
NSLog(#"MobFox: did load ad and placed on screen");
// animate banner into view
//[UIView beginAnimations:#"MobFox" context:nil];
//[UIView setAnimationDuration:1];
banner.frame = CGRectMake(135, 140, 320, 50);
[UIView commitAnimations];
}
- (void)mobfoxBannerView:(MobFoxBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
NSLog(#"MobFox: did fail to load ad: %#", [error localizedDescription]);
// animate banner outside view
//[UIView beginAnimations:#"MobFox" context:nil];
//[UIView setAnimationDuration:1];
banner.frame = CGRectMake(-800, self.view.bounds.size.height - 240, 320, 50);
[UIView commitAnimations];
}
//MOBFOX ENDS HERE
Example of where I would like to call bringSubViewToFront:bannerView but can't
-(void) settitleMenuToFront {
[self.view bringSubviewToFront:titleScreenImg];
[self.view bringSubviewToFront:highScoreTable];
[self.view bringSubviewToFront:ContinueButton];
[self.view bringSubviewToFront:highscoreButton];
[self.view bringSubviewToFront:newgameButton];
if (loadingScreen.alpha > 1) {
[self.view bringSubviewToFront:loadingScreen];
}
}
You need to add an instance variable, or ivar. The most straightforward way to do this is by adding a property and letting the compiler add the variable (the ivar) to store the property value.
In your header file, add a line:
#property (nonatomic, retain) MobFoxBannerView *bannerView;
In your implementation, add this line near the top:
#synthesize bannerView;
Release it in -dealloc
-(void)dealloc {
// ...
[bannerView release];
}
Then when you create the view, set the property:
self.bannerView = [[[MobFoxBannerView alloc] initWithFrame:
CGRectMake(-800, self.view.bounds.size.height - 240, 320, 50)]
autorelease];
You can then refer to self.bannerView anywhere in the rest of your code.
You need to create an instance variable that you will release and set to nil in viewDidUnload and then just release in dealloc. If using Apple's llvm 2 you can do this in a class extension otherwise add it to the header file.
I can see the launch image(png at the root of the project, sized:320x480 pixels) on the iPhone simulator and iPhone device.
And then,I want to do transparent it(the launch image) slowly .(alpha = 0.0;)
But I cannot do it.though I tried variously.
Thank you,
Katsumi
Take a look at UIView animation methods. Method like animateWithDuartion should be sufficient for your goal. Your fade-out animation in the simplest implementation will looks like following:
[UIView animateWithDuration:1 animations:^(void){self.splashImage.alpha = 0.0f;}];
When the app launches you'll have to immediately create a new instance of the image via UIImageView and throw it on the main window. Then once you get access to that UIView you can use basic animation techniques to fade it out, such as -animateWithDuration:animations:.
Of course you'll want to setup some type of view below this, so you have your main app's content available right away.
Code sample:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// PLACE YOUR APP LAUNCH CODE HERE
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default"]];
[self.window addSubview:imageView];
[imageView release];
[UIView animateWithDuration:2.0 animations:^{
imageView.alpha = 0.0;
[imageView removeFromSuperview];
}];
return YES;
}
I am trying to get a busy view displayed during a search process however it never seems to display.
What I am trying to achieve
User clicks on search button once they have entered the text in a UISearchBar.
The text entered is delegated to searchBarSearchButtonClicked.
Show a "Busy view" which is a UIView containing a UIActivityIndicatorView to indicate the search is underway.
Perform a search which communicates with a website.
On search completion remove the "Busy View".
Whats wrong
The search process is working fine, using the debugger I can see it moving through the searchBarSearchButtonClicked function fine however the "Busy View" never appears. The search takes 2-3 seconds so in theory I should see my "Busy View" appear for those 2-3 seconds.
Code Attempt 1 - Add and remove the "Busy View" from the superview**
- (void)searchBarSearchButtonClicked:(UISearchBar *)activeSearchBar {
[activeSearchBar setShowsCancelButton:NO animated:YES];
[activeSearchBar resignFirstResponder];
[busyView activateSpinner]; //start the spinner spinning
[self.view addSubview:busyView]; //show the BusyView
Search *search = [[Search alloc]init];
results = [search doSearch:activeSearchBar.text];
[busyView deactivateSpinner]; //Stop the spinner spinning
[busyView removeFromSuperview]; //remove the BusyView
[search release]; search = nil;
}
Results Of Attempt 1 - It does not appear, however if I comment out the removeFromSuperview call the Busy View remains on screen.
Code Attempt 2 - using animations
- (void)searchBarSearchButtonClicked:(UISearchBar *)activeSearchBar {
[activeSearchBar setShowsCancelButton:NO animated:YES];
[activeSearchBar resignFirstResponder];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop)];
[busyView activateSpinner]; //start spinning the spinner
[self.view addSubview:busyView]; //show the busy view
[UIView commitAnimations];
Search *search = [[Search alloc]init];
results = [search doSearch:activeSearchBar.text];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop)];
[busyView deactivateSpinner]; //sets stops the spinner spinning
[busyView removeFromSuperview]; //remove the view
[UIView commitAnimations];
[search release]; search = nil;
}
Results of attempt 2 - Did not see the "Busy View" appear
Well, Here's my solution:
Create singleton class MyLoadingView. This class should contain show and hide static methods.
In MyLoadingView constructor you should manually create a view with semi-transparent black background and activityview inside of it. Place this view into [[UIApplication sharedApplication] keyWindow]. Hide it.
[MyLoadingView show] invocation just brings myLoadingView object to front in it's container: [[[UIApplication sharedApplication] keyWindow] bringSubviewToFront:myLoadingViewSharedInstance];. Also don't forget to start activityview animation.
[MyLoadingView hide] stops activityview animation and hides sharedInstanceView.
Please notice, that you need to invoke [MyLoadingView show] in a separate thread.
UI changes in Cocoa only take effect the next time your code returns control to the run loop. As long as your search task runs synchronously on the main thread, it will block execution, including UI updates.
You should execute the time-consuming task asynchronously in the background. There are a number of options for this (NSOperation, performSelectorInBackground:..., Grand Central Dispatch, ...).