I am trying to create a 1-2 second splashcreen for my application using a modal view controller however when i try to dismiss the view my application crashes with a bad access error. So in my application delegate i have:
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//create window and show it
window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
window.backgroundColor = [UIColor greenColor];
[window makeKeyAndVisible];
//create the main view controller and add its view to the window
mainViewCtrl = [MainViewController alloc];
[window addSubview:mainViewCtrl.view];
//show splash screen
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"default.png" ofType:nil]];
splashViewCtrl = [[UIViewController alloc] init];
splashViewCtrl.view = [[UIImageView alloc] initWithImage:image];
[mainViewCtrl presentModalViewController:splashViewCtrl animated:NO];
//setup callback to dismiss
[self performSelector:#selector(hideSplash) withObject:nil afterDelay:2.0];
return(true);
}
//hide splash screen callback
- (void)hideSplash {
[[self mainViewCtrl] dismissModalViewControllerAnimated:YES];
}
And this all works perfectly fine except when the hideSplash is called after 2 seconds the application crashes with a EXC_BAD_ACCESS. If i comment out the perform selector line and call the hidesplash immediately after like so:
[mainViewCtrl presentModalViewController:splashViewCtrl animated:NO];
[self hideSplash];
The modal view is properly dismissed. I'm fairly sure this is a memory management problem but i'm not sure exacty what i'm doing wrong here. Does anyone have any ideas of what this could be or how to properly debug this so i can delay the dismissal?
Thanks
This looks weird:
mainViewCtrl = [MainViewController alloc];
Try adding the initialisation call to it.
//show splash screen
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"default.png" ofType:nil]];
splashViewCtrl = [[UIViewController alloc] init];
splashViewCtrl.view = [[UIImageView alloc] initWithImage:image];
[mainViewCtrl presentModalViewController:splashViewCtrl animated:NO];
Change the above to this below:
//show splash screen
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"default.png" ofType:nil]];
splashViewCtrl = [[UIViewController alloc] init];
splashViewCtrl.view = [[UIImageView alloc] initWithImage:image];
[mainViewCtrl presentModalViewController:splashViewCtrl animated:NO];
[mainViewCtrl release]; //Add this line !!!!
Related
I've made a project and implemented the folder project and now I've set up a subview which is displayed aboce the folder like on the picture. On the popup there's a image and I would like to do it like this that if I tap the image a new controller with the whole image will displayed. I've set up all correctly...However, I tried to change the subview etc. THIS Navigationcontroller never appears at the top of all "layers". it appears in the folderviewcontroller. By the way, the Navcontroller is set up by this project: https://github.com/mwaterfall/MWPhotoBrowser and the Popup was set up through this: https://github.com/kgn/KGModal
So here's my code:
-(IBAction)mehr:(id)sender {
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 280, 440)];
cubut = [UIButton buttonWithType:UIButtonTypeCustom];
[cubut addTarget:self
action:#selector(dothis:)
forControlEvents:UIControlEventTouchUpInside];
[cubut setTitle:#"Show View" forState:UIControlStateNormal];
cubut.frame = CGRectMake(5, 70, 270, 200);
[contentView addSubview:cubut];
- (IBAction)dothis:(id)sender {
MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
// Set browser options.
browser.wantsFullScreenLayout = YES;
browser.displayActionButton = YES;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:browser];
[self presentModalViewController:navController animated:YES];
NSMutableArray *photos = [[NSMutableArray alloc] init];
MWPhoto *photo;
photo = [MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"star" ofType:#"png"]];
photo.caption = #"The star is soo beateful...";
[photos addObject:photo];
self.photos = photos;
}
- (MWPhoto *)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index {
if (index < _photos.count)
return [_photos objectAtIndex:index];
return nil;
}
- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser {
return _photos.count;
}
And the picture:
(The button is set to custom so you cant see it...it has the same frame like the image)
So this was not finished so I have to awnser my own questions that I didnt found a solution for this.
I am making an app in which I have put a default.png in the areas provided and added sleep(5); to my app delegate and currently it runs fine.
What I need to do is add more than one image when the app starts, so that I get one splash screen for 2.5 seconds and another one for 2.5 seconds.
How can I show 2 splash screens at start up?
Two splash screens are not possible. Create a viewcontroller with UIImageView filled with second image and show it for 2.5 seconds.
Just simply add your image to your view controller and after 2.5 second, remove it from your view.
You can easily implement your view on top of the main view but in your appDelegate. For example, if you want a splash image that fades out to the main view: (or a default image that seems to fade out: just put the same image on the splash screen and the default screen). This gives you also the right orientation as long as it is the main view's.
Just add it in your
application:(UIApplication *)application didFinishLaunchingWithOptions:
method:
UIImageView*imageView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"your_default_image_or_First.png"]];
[[firstViewController view] addSubview:imageView];
[[firstViewController view] bringSubviewToFront:imageView];
[NSThread SleepForTimeInterval:(2.5)];
[imageView setImage:[UIImage imageNamed:#"your_default_image_or_Second.png"]]
// as usual
[self.window makeKeyAndVisible];
//now fade out splash image
[UIView transitionWithView:self.window duration:1.0f options:UIViewAnimationOptionTransitionNone animations:^(void){imageView.alpha=0.0f;} completion:^(BOOL finished){[imageView removeFromSuperview];}];
Hi please try with following code its really hwlp full for you dear i suggested to use this one.....
-(BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:self.window.bounds] autorelease];
UIImage *image = [UIImage imageNamed:#"Welcome.png"];
if (!image)
{
NSLog(#"Something went wrong trying to get the UIImage. Check filenames");
}
imageView.image = image;
[self.window addSubview:imageView];
[self.window makeKeyAndVisible];
[self performSelector:#selector(removeFirstSplash:) withObject:imageView afterDelay:3];
return YES;
}
-(void)removeFirstSplash:(UIImageView *)oldImageView
{
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:self.window.bounds] autorelease];
UIImage *image = [UIImage imageNamed:#"Splash.png"];
imageView.image = image;
[self.window addSubview:imageView];
[self performSelector:#selector(removeSecondSplash:) withObject:imageView afterDelay:3];
[oldImageView removeFromSuperview];
}
-(void)removeSecondSplash:(UIImageView *)oldImageView
{
[self.window addSubview:self.navigationController.view];
[oldImageView removeFromSuperview];
}
Trying to programmatically add a splash image that hangs around for a specified amount of time. I have Default.png already imported into my project, and I see it flicker as the launch image when the simulator launches. I'm not sure how to make Default.png hang around as the splash image.
In AppDelegate.m, inside didFinishLaunchingWithOptions I do the following:
MyViewController *mvc = [[MyViewController alloc] init];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:mvc] autorelease];
[navController setNavigationBarHidden: YES];
MyViewController as you might suspect, is a subclass of UIViewController, and in the loadView method I do the following:
self.mainView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view = mainView;
mainView.backgroundColor = [UIColor yellowColor];
Then I created SplashScreenViewController, also a subclass of UIViewController, and in the loadView method I do the following:
splashView = [[[UIImageView alloc] initWithFrame:CGRectMake(0,0, 320, 480)] autorelease];
splashView.image = [UIImage imageNamed:#"Default.png"];
Finally, back in AppDelegate I have the following after makeKeyAndVisible:
SplashScreenViewController *splashScreen = [[SplashScreenViewController alloc] init];
splashScreen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[navController presentModalViewController:splashScreen animated:NO];
I think I'm just stuck understanding how to tie all the UIViewController subclasses together, and how to reference them from AppDelegate (or whether I should even be doing that), etc. Any tips are appreciated. I can clarify if my question is muddy.
You can move this to MyViewController's viewDidLoad
SplashScreenViewController *splashScreen = [[SplashScreenViewController alloc] init];
splashScreen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[navController presentModalViewController:splashScreen animated:NO];
Or you could do this in you AppDelegate, before makeKeyAndVisible
splashView = [[[UIImageView alloc] initWithFrame:CGRectMake(0,0, 320, 480)] autorelease];
splashView.image = [UIImage imageNamed:#"Default.png"];
[self.window addSubview:splashView];
[self.window bringSubviewToFront:splashView];
What's your plan for dismissing the view?
inside the UIViewController, the tempview2 is not showing up at all. only tempview is showing up.
-(id) init:(NSData*) imageData
{
if ((self = [super init])) {
tempimage= [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"pic1" ofType:#"png"]] autorelease];
tempview=[[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
[tempview setImage:tempimage];
[self.view addsubview tempview];
}
return self;
}
-(void) viewdidload{
tempimage2= [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"pic2" ofType:#"png"]] autorelease];
tempview2=[[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
[tempview2 setImage:tempimage2];
[self.view addsubview tempview2];
}
if I do this then everything is OK,
-(id) init:(NSData*) imageData
{
if ((self = [super init])) {
tempimage= [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"pic1" ofType:#"png"]] autorelease];
tempview=[[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
[tempview setImage:tempimage];
[self.view addsubview tempview];
tempimage2= [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"pic2" ofType:#"png"]] autorelease];
tempview2=[[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
[tempview2 setImage:tempimage2];
[self.view addsubview tempview2];
}
return self;
}
This is not a direct answer to your question but a good practice of viewcontroller initialization and view loading in general:
In the init method you should only initialize ivars or other class data which does not pertain to the view. Doing otherwise breaks the notion of lazy loading. During the init method of you view controller the view does not exist yet.
In the viewDidLoad method you should perform your view setup. At this stage the view is actually loaded and it is the time to set it up properly.
I would encourage you to therefore move your view setup calls into the viewDidLoad and see if the problem persists or not.
Good luck.
I agree with MiKL.
But anyway getting back to your question did you forget to call [super viewDidLoad]? Maybe that's the issue here?
Also, as a best practice, release views after adding them as subviews to something else (adding a view as a subview to another view increases it's retain count).
I used to use the old-school method of adding an overlay to the camera screen, and that worked fine. However, since 3.1 came out, Apple is insisting that I use the API to add an overlay. I quickly got the overlay to work, but it seems that if I use the custom overlay, then the move & resize screen is not responsive, I can only use or retake, can't actually resize & move. The code I am using is below. I have tried several variations, but the only thing that actually enables the move & resize is to remove the line that adds the custom overlay view.
Any ideas?
UIImage *image = [UIImage imageNamed:#"camera-template-long.png"];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] ;
imgView.image = image;
UIView *overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
overlayView.opaque = NO;
[overlayView addSubview:imgView];
UIImagePickerController* picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.showsCameraControls = YES;
picker.cameraOverlayView = overlayView;
picker.delegate = self;
picker.allowsEditing = YES;
[self presentModalViewController:picker animated:YES];
Set both allowsEditing/showsCameraControls properties to NO, prepare your original view to cameraOverlayView, and use takePicture method.
Then, imagePickerController:didFinishPickingMediaWithInfo: will be called directly.
Please try the following code:
- (void)foo {
UIImagePickerController *controller = [[[UIImagePickerController alloc] init] autorelease];
controller.sourceType = UIImagePickerControllerSourceTypeCamera;
controller.cameraOverlayView = self.cameraOverlay;
[self performSelector:#selector(moveOverlayViewToSublayer:) withObject:controller afterDelay:0.1f];
controller.delegate = self;
[self presentModalViewController:controller animated:YES];
}
- (void) moveOverlayViewToSublayer:(UIImagePickerController*)controller {
CALayer *aLayer = self.cameraOverlay.layer.superlayer;
controller.cameraOverlayView = nil;
[aLayer addSublayer:self.cameraOverlay.layer];
}
I hope it will work well.
The entire issue goes away once you use [overlayView setUserInteractionEnabled:NO]; to stop the overlay view from handling the input.
http://www.techques.com/question/1-10178214/cameraOverlayView-prevents-editing-with-allowsEditing
This works perfectly for me. I tried to disable userInteractionEnabled but in vain.