I want to add a logo view as iPhone application lunch. I code as follows
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
UIImage image = [[UIImage alloc] imageWithContentsOfFile:#"1.jpg"];
UIImageView view = [[UIImageView alloc] initWithImage:image];
[window addSubViews:view];
[NSThread sleepForIntervalTime:10];
[view removeFromSubview];
[window addSubview: navigationController.view];
[window makeKeyAndVisible];
}
But simulator can't display as I want.just display navigationController's view.
I think the reason is iPhone render the first view after "applicationDidFinishLaunching"
Are there other solutions about that?
Just add the image you want to be the LOGO to your project with the name: Default.png
It will automatically become the startup screen for your application.
Your approach won't work. applicationDidFinishLaunching delegate runs after all the loading was done. Besides, delaying it for 10 seconds won't be accurate since application might load faster on some devices than others.
Pablo is right - you can just use the Default.png for this.
However, your code will never work for two reasons.
1)
The main thread of the application is the UI thread - the one responsible for dealing with updating the interface and this is the thread that is running your applicationDidFinishLaunching:.
If you just call [NSThread sleepForIntervalTime:10] the thread will sleep. However, this also means that while the thread is sleeping, the UI won't get updated. Then, when you call [view removeFromSuperview] it will remove the image and carry on. You will never get to see the image!
To get your code to work you should do something like this :
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
[window addSubview: navigationController.view];
UIImage *image = [UIImage imageWithContentsOfFile:#"1.jpg"];
UIImageView *view = [[UIImageView alloc] initWithImage:image];
[window addSubView:view];
[view release];
[NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(removeImage:) userInfo:view repeats:NO];
[window makeKeyAndVisible];
}
- (void) removeImage:(NSTimer *)timer {
UIImageView *view = (UIImageView *)timer.userInfo;
[view removeFromSuperview];
}
This code will show an image for 10 seconds and then remove it. However, if you just want an image at launch, using Default.png is definately the way to do it!
2)
You have added the navigator view infront of your image - in the code above, I have moved adding the navigator's view to be before the UIImage. This means that the image will be infront of the navigator for the 10 second delay until it is removed, revealing the navigator view.
Hope this helps,
Sam
Related
I am currently trying to add a Activity Indicator View to my Splashscreen. It only should appear once - at the first start of the App. Some images are created that are needed for the App, but it takes some time.
While the images are created, the Splashscreen is still visible. So I thought it could maybe be possible to add a Activity Indicator as a Subview of the Splashscreen or at least add it somehow over the Splashscreen.
Is there a possibility to make this possible?
Thanks for your help in advance.
You will need to add the "Splashscreen" as top most view to your window, the "splashcreen" it self is not a view. The system wil just display the default.png:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
splashScreen = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, -20.0f, 320.0f, 480.0f)];
splashScreen.backgroundColor = [UIColor blackColor];
splashScreen.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Default" ofType:#"png"]];
[self.window addSubview:splashScreen];
[self.window makeKeyAndVisible];
[self performSelector:#selector(applicationDidStart) withObject:nil afterDelay:0.1];
return YES;
}
splashScreen is a class variable, you could add an Activity Indicator to the splashView.
Then in the applicationDidStart did start methods place the code that will take some time:
- (void) applicationDidStart {
// some thing that takes a while
[splashScreen removeFromSuperView];
[splashScreen release], splashScreen = nil;
}
I dont think it is possible to add a subview to the Splash Screen.
There is a workaround where in you can push an intermediate view on applicationDidFinishLaunching and have the background image of the view as same as that of the splash screen.
Now you can do the stuff where your images are created on this view.
Once images are created, Call a method in applicationDelegate which will pop the intermediate view and add your regular view.
Hope this helps you.
When I receive a memory warning in my navigation based iPhone App the background image disappears in the previously allocated navigation controllers.
The background image is set as the background property of a UIView. This view is then added to the main window of the App delegate:
UIView *backgroundView = [[UIView alloc] initWithFrame: window.frame];
backgroundView.backgroundColor = [UIColor colorWithPatternImage:[[Utilities sharedManager] getImageWithName:#"Hintergrund2"]];
backgroundView.tag = 56789;
[window addSubview:backgroundView];
[backgroundView release];
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
After I received the memory warning message and pressed the back button of the navigation controller the previous navigation controller shows up the normal Apple gray background. I have to navigate back to my home screen and navigate forward to "reset" the background image.
Can anyone tell me why the background disappears? It is not because of the image, when I set the background to a standard UIColor like blackColor the background (color) also disappears.
Thank you in advance for your help!
regards
Phil
It is undefined what the OS does with stuff added directly to the main UIWindow in case of low memory situations.
Maybe consider using a simple UIViewController for the background? You will then at least get callbacks when there is a low memory situation.
First, you should probably add your controller to the window like this:
window.rootViewController = navigationController;
I haven't tested this, but perhaps you can set the background color of the window directly:
window.backgroundColor = [UIColor colorWithPatternImage:[[Utilities sharedManager] getImageWithName:#"Hintergrund2"]];
If that doesn't work, you'll need a better way to recreate your view state in low memory situations. The most standard way to do this is by defining the background in each xib, which is reloaded. Alternatively, you could catch the low memory warning and recreate as needed by seeing if your backgroundView has a superview.
Make sure that you are setting the calling self.view.backgroundColor = [UIColor clearColor]; in the view controller's - (void) viewDidLoad otherwise the window's image will not be displayed.
- (void) viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
...
}
My problem was that I set the view's backgroundColor when it is initialized
MyTableViewController *myTVC =
[[MyTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
myTVC.view.backgroundColor = [UIColor clearColor];
and not in - (void) viewDidLoad.
In this situation, the UITableViewController's view's background color was set after it was initially created. However after a low memory warning, the UIViewController's that were not displayed have - (void) viewDidUnload called on them. That deallocate their views. Just before the UIViewController was to be displayed again, - (void) viewDidLoad was called and created a new view, but the view's background color was set to the default which is not clear.
I have a Tab Bar Application and I want to simply display a view (splash screen) once the didFinishLaunchingWithOptions method loads up the tab bar controller. Why is this so hard? Please show me how I'd load up and show a Xib file called SplashView.xib below and display it:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the tab bar controller's view to the window and display.
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
// Load up and show splash screen Xib here
return YES;
}
First thing I'd mention is that splash screens are specifically frowned upon in the HIG. Especially ones that only serve to make the user wait & stare at some logo they don't care about.
Now that rant is out of the way, I'll assume that you probably have some loading going on that you'd like to have happen before the tabs are displayed.
In this case I don't load up a tab bar in the MainWindow.xib. Instead I launch my single view (with XIB) that does the loading. The reason is this: You'll pay for the loading of all of those views before you can even see your splash screen.
In the case of loading data, sometimes these tabs depend on this data being loaded, so it makes more sense to wait to load up the tab bar controller.
The app delegate ends up looking like this:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window makeKeyAndVisible];
[window addSubview:splashController.view]; //this assumes MainWindow.xib defines your splash screen, otherwise....
UIViewController *splashController = [[SplashController alloc] initWithNibName:#"SplashController" bundle:nil];
splashController.delegate = self;
[window addSubview:splashController.view];
//hang on to it in an ivar, remember to release in the dealloc
}
Then in the splash screen controller, when I'm done loading, I do this:
-(void)doneLoading {
[self.delegate performSelector:#selector(splashScreenDidFinishLoading)];
}
Of course self.delegate doesn't exist, and it can be added simply like this:
//header
#property (nonatomic, assign) id delegate;
//implementation
#synthesize delegate;
Then just make sure and implement that method on the app delegate:
-(void)splashScreenDidFinishLoading {
//load up tab bar from nib & display on window
//dispose of splash screen controller
}
I've used this pattern in a handful of apps and is simple and works well. You could also choose to do a nice transition animation in the method above.
Hope this helps.
In your app delegate's header file:
#interface AppDelegate {
...
IBOutlet UIView *splash; // add this line
}
In IB open the SplashView.xib, set the File Owner's class to the class of your app delegate, connect the splash outlet. Add this to show a splash view:
[[NSBundle mainBundle] loadNibNamed: #"SplashView" owner: self options: nil];
[window addSubview: splash];
You will possibly want to hide the splash view too:
[splash removeFromSuperview];
[splash release];
splash = nil;
You could use UIView animation block to fade out the splash view to be extra-cool. That said, splash screens are evil.
I think the app delegate is indeed a better place for this kind of stuff.
I would do something like:
UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"Splash.png"]];
[imageView setCenter:CGPointMake(240, 160)];
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[self.view addSubview:imageView];
[imageView retain];
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self //display for 3 secs
selector:#selector(continueLoadingWhatever:)
userInfo:nil
repeats:NO];
And then...
- (void)continueLoadingWhatever:(id)sender {
//do whatever comes after here
}
I probably wouldn't do this in the app delegate, but in the root view controller. You should never have to add anything unnecessary directly to the window, especially if it contains interaction (I know this doesn't).
I am trying to create a UINavigationController with a background Image...
I have the following code at the top of the class where I implement the UINavigationController.
#implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
UIImage *img = [UIImage imageNamed:#"header.jpg"];
[img drawInRect:CGRectMake(0, 0, self.frame.size.width,self.frame.size.height)];
}
#end
Then, inside my #implementation of my controller in the "viewDidLoad" function, I have the following...
MainViewController *controller = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:controller];
self.navController = nav;
[nav release];
I know I am close, because everything is working almost perfectly, except the image is 150px in height, and it's being squished down to a smaller size (doing a log of self.frame.size.height is giving me 44.0000) but is pushed down a certain number of pixels from the top...
I know I am close, but if anyone could help me out, it would be muchly appreciated.
Thank you,
--d
You really need to actually make your image the same size as your navigation bar. Don't try to do this unless you really have art that was made for a UINavigationBar.
This code will work, so long as the dimensions are correct:
- (void)drawRect:(CGRect)rect {
[img drawInRect:rect];
}
To support different orientations with differently-sized navigation bars, just send -[UIApplication statusBarOrientation] (I've heard from a lot of people that -[UIDevice orientation] doesn't work as expected, but I haven't tried it).
The docs say that the whole subview hierarchy can be created in -loadView. But there's also this -viewDidLoad method which sounds nice to ovewrite for actually building the hierarchy, when the view loaded. I guess it's a matter of taste only. But maybe doing so in -viewDidLoad hast the advantage that the view controller already adjusted the frame of the view correctly to accomodate for the status bar or any other kind of bar like tab bar or tool bar?
viewDidLoad is called after the view hierarchy is built. loadView is supposed to build the hierarchy and set the view property if you are not loading from a NIB file.
viewDidLoad is also called after a memory warning if you're view got unloaded. When you get a memory warning viewDidUnload is called to give you a change to release objects that can be easily recreated in viewDidLoad.
Read the "Subclassing Notes" and "Memory Management" sections of the class description to better understand how it works.
I think the logic behind it is that in loadView you build elements, i.e. instantiate and allocate memory, this being the most costly action. So when [super loadView] has been called all the way up the ladder, all views are ready to be displayed and the expensive part is over.
In - (void) viewDidLoad you populate the views with data, viewDidLoad "know" all elements are ready to have text set on them, values, content etc.
UINavigationControllers etc. can benefit from knowing when everything is ready as to start animating view on to the screen. If you place all the instantiation/allocation in the viewDidLoad you force the controller to do everything, including being animated on screen, at the last moment. I don't know the exact details, but this is what I get from the documentation and the "life-cycle" of the UIViewController
I usually do it like this:
- (void)loadView {
[super loadView];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 20.0f, 320.0f, 460.0f)];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bg02.png"]];
[container addSubview:imageView];
[imageView release];
UIImageView *background = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bg_search.png"]];
[container addSubview:background];
[background release];
UILabel *textlabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10.0f, 200.0f, 20.0f)];
[self setLabel:textlabel];
[container addSubview:self.label];
[textlabel release];
[self setView:container];
[container release];
}
- (void)viewDidLoad {
[self.label setText:#"I am ready!"];
[super viewDidLoad];
}
I sometimes use the viewWillAppear to set data, if it is a view controller that sports modalViewControllers or pushes a new viewController where a user sets data that needs to be updated on the parent when popping the view again (e.g. a UITableViewController with a list of songs is pushed, the user selects a song and the controllers pops and the parent now displays the song title the user selected etc.) Any case wher the view goes on/off screen often, but needs to display newly changed data.