IOS 8 have crash on orientation change....
first we are showing a report as like here..
-(void)didShowReport:(NSString *)fileName andFlag:(BOOL) isWeightReport
{
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Document_Picker" bundle:nil];
UINavigationController *nav = [storyBoard instantiateViewControllerWithIdentifier:#"reportNav"];
NSLog(#"topviewcontrolle - %#",[nav topViewController]);
SSReportPreviewViewController *reportPreview = (SSReportPreviewViewController *) [nav topViewController];
reportPreview.fileName = fileName;
//reportPreview.delegate = self;
reportPreview.title = [fileName lastPathComponent];
if(isWeightReport)
reportPreview.mailSubject = NSLocalizedString(#"weightsummaryreport", #"");
else
reportPreview.mailSubject = NSLocalizedString(#"pricesummaryreport", #"");
[nav setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:nav animated:YES completion:nil];
}
after this we are cancelling that view controller using
- (IBAction)onCancel:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
after canceling we rotating....crash happening....
error showing.....as like below
*** -[UINavigationController _viewControllerForSupportedInterfaceOrientationsWithDismissCheck:]: message sent to deallocated instance 0x16ad08c0
Are you presenting this after the user presses a button in an action sheet? (Or maybe an alert view?)
iOS 8 now shows action sheets in their own window. (Check which window is key from the app delegate.) If you present a modal before that window is dismissed, the modal will be presented from the action sheet's window (or at least be referenced from it and brought up during rotations.)
Try using didDismissWithButtonIndex: instead of willDismissWithButtonIndex: .
If that doesn't work, try dispatching your presentation with a 0.1 or 0.2 second delay. (Sometimes just dispatching to the main queue to give a single run loop delay is enough.)
Related
Im using this code to try and show a alert message on the iphone
[[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:alert animated:YES completion:nil];
it works fine.
But is it possible to show the alert message on top of another sharing dialog also shown using presentViewController:
at the moment it shows a warning in the console and the alert does not show, only shows the popup for the sharing activity?
I can get this to work using UIAlertView but that deprecated now
For future reference, it would be good to include the text of the warning you're receiving in the question as well.
My guess is it's along the lines of:
Warning: Attempt to present <UIAlertController: 0x7fe676036000> on <ViewController: 0x7fe674e02f50> which is already presenting <UIActivityViewController: 0x7fe67580f800>
Which basically indicates you can't present another view controller using a view controller that's already presenting a separate view controller.
One way you could work around this is to climb the presentedViewControllers to locate a view controller which isn't already presenting and then present from that (in your case you should only need to move up one presentedViewController to your UIActivityViewController).
Here's an example using the UIWindowScene to grab the rootViewController (iOS 13+), but should basically be the same idea for using the appDelegate's window as well:
- (IBAction)showShareSheetAndAlert:(id)sender {
UIImage *homerImage = [UIImage imageNamed:#"Homer"];
UIActivityViewController *shareSheet = [[UIActivityViewController alloc] initWithActivityItems:#[homerImage] applicationActivities:nil];
[self presentViewController:shareSheet animated:YES completion:^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"Test Alert" message:#"Here's a test alert on top of a share sheet" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:#"Dismiss" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:dismissAction];
UIWindowScene *windowScene = (UIWindowScene *)[[[[UIApplication sharedApplication] connectedScenes] allObjects] firstObject];
UIViewController *viewControllerToPresentOn = windowScene.windows.firstObject.rootViewController;
// keep climbing the presented view controllers until we find the top one which isn't presenting
while (viewControllerToPresentOn.presentedViewController != nil) {
viewControllerToPresentOn = viewControllerToPresentOn.presentedViewController;
}
[viewControllerToPresentOn presentViewController:alert animated:YES completion:nil];
}];
}
Which will result in this:
I developed test application on iOS 7 that pick the music from music library using MPMediaPickerController.
But when I present the media picker controller,it shows empty screen.
This is the code
(void) pickSong
{
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
mediaPicker.delegate = self;
mediaPicker.allowsPickingMultipleItems = NO;
mediaPicker.prompt = NSLocalizedString(#"Select Your Favourite Song!", nil);
[mediaPicker loadView];
[self.navigationController presentViewController:mediaPicker animated:YES completion:nil];
}
#pragma mark - MPMediaPickerController delegate
(void) mediaPicker:(MPMediaPickerController *) mediaPicker2 didPickMediaItems:(MPMediaItemCollection *) mediaItemCollection {
[self dismissViewControllerAnimated:YES completion:nil];
MPMediaItem *mediaItem = [[mediaItemCollection items] objectAtIndex:0];
self.item.soundName = [mediaItem valueForProperty:MPMediaItemPropertyTitle];
self.item.soundUrl = [[mediaItem valueForProperty:MPMediaItemPropertyAssetURL] absoluteString];
}
(void) mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker{
[self dismissViewControllerAnimated:YES completion:NULL];
}
Please help me out.
This is an iOS bug, but it only occurs when running a 32 bit build on a 64 bit (A7) device (Only iPhone 5S for now). To work around it, add a 64 bit architecture to your app. (Open build settings in xcode, and change Architecture from $ARCHS_STANDARD to $ARCHS_STANDARD_INCLUDING_64_BIT.) You will then probably need to fix a number of compile, link and runtime issues. See Apple's 64-Bit Transition Guide.
Seems like there is a bug in ios7 where it doesn't like to be presented inside a uinavigation controller - try presenting it directly from a view controller.
I had the same problem and for me the solution was a combination of two of the solutions presented here. First I had to convert my app to be 64-bit ready by changing Architectures to "standard... (including 64-bit)". Once I corrected all the warnings that caused, I had to change the MPMediaPickerController to be presented modally rather than on the navigation stack:
- (IBAction)didSelectMusicPicker:(id)sender {
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
picker.delegate = self;
picker.allowsPickingMultipleItems = YES;
picker.prompt = NSLocalizedString (#"Add songs to play", "Prompt in media item picker");
//[self.navigationController pushViewController:picker animated:YES];
[self presentViewController:picker animated:TRUE completion:NULL];
}
Of course, I also needed to change mediaPicker:didPickMediaItems: and mediaPickerDidCancel: to use dismissViewControllerAnimated. Once all that was fixed, the picker worked as expected on both iPhone 4 and iPhone 5S running iOS 7.
a thought: is the presented screen completely empty, or are you getting the navigation bar at the bottom but with no tracks listed? I've noticed that as of iOS 7 the picker now defaults to opening to the Playlist tab (it used to open to Albums, if I recall)… if you have no playlists on the device that would account for the empty screen…
I can see the list of songs and select the songs. But I cannot dismiss the view controller on pressing "Done". I've tried PresentViewController since Modal controller is deprecated.
- (IBAction) showMediaPicker: (id) sender {
picker =
[[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAnyAudio];
picker.delegate = self;
picker.allowsPickingMultipleItems = YES;
picker.prompt = NSLocalizedString (#"AddSongsPrompt", #"Prompt to user to choose some songs to play");
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault animated:YES];
[self.picker removeFromParentViewController];
[self presentViewController:picker animated:YES completion:nil];
// [picker release];
}
// Responds to the user tapping Done after choosing music.
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection {
[self.picker removeFromParentViewController];
[self dismissViewControllerAnimated:YES completion:nil];
//
[self.delegate updatePlayerQueueWithMediaCollection: mediaItemCollection];
// [self.mediaItemCollectionTable reloadData];
// [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque animated:YES];
}
I've tried RemovefromSuperview also, nothing seems to work. I'm testing this on an iPhone 6 simulator and an iPhone 5 with iOS 8.1.3.
Anyone???
I also have the same problem before. But I found out just need to restart the device after upgrade. The music picker appear again.
I have been trying everything to work this out. I get a notification when the app is closed with 2 custom items, a type and an id. The type is supposed to tell me which view to load, and the id is supposed to tell the app which row to get from the database. I am going through hell trying to figure this out.
I need to click on the notification and have it take me to the relevant record. So far I have been almost successful with two different methods that I'll outline below.
I should also point out that I know the payload is working correctly from APNS as I've debugged it to death :)
The first thing I tried was as follows:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSString *itemType = [[userInfo objectForKey:#"T"] description];
NSString *itemId = [[userInfo objectForKey:#"ID"] description];
self.window=[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// type 1 = call, type 2 = contact
if ([itemType isEqual: #"1"]) {
Leads_CallsDetailViewController *callView = [[Leads_CallsDetailViewController alloc] init];
[callView displayItem:itemId];
[self.window addSubview:callView.view];
[self.window makeKeyAndVisible];
} else if([itemType isEqual: #"2"]) {
Leads_ContactsDetailViewController *contactView = [[Leads_ContactsDetailViewController alloc] init];
[contactView displayItem:itemId];
[self.window addSubview:contactView.view];
[self.window makeKeyAndVisible];
}
}
With this one, I have a method on the detail views called displayItem that I was going to use to get the data from the api and then display it. This did something, but it looked like the view never really loaded. I have a scrollview and various buttons on the page, but all that ever got loaded from addSubview was a background image. Nothing ever really happened to fully load the view. I wasn't sure how to handle that.
The second thing I tried was to go directly to the view like this:
NSString *storyboardId = #"Leads_Calls_SB";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:storyboardId];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initViewController;
[self.window makeKeyAndVisible];
This one seems to load the view functioning and nice looking with two major caveats. 1. I'm not sure how to pass data to it, and 2. It didn't like it when I tried to pop back and it also got angry when I tried to segue pushes from there, almost as if there was no navigation controller for the view, even though the entire application is embedded in a navigation controller.
Thanks so much for your help. If anyone can help me figure this out I'll be indebted to you.
Normally for this requirement I would do this..
Use NSNotificationCenter and post a notification from didReceiveRemoteNotification.
[[NSNotificationCenter defaultCenter] postNotificationName:#"notificationReceived" object:self userInfo:userInfo];
Subscribe to it from the VC from where you can open your details view to show the message.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationReceived:) name:#"notificationReceived" object:nil];
If you are instantiating the VC yourself and not using segue. you can do this..
UIStoryboard* storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
detailVC = [storyBoard instantiateViewControllerWithIdentifier:#"detailVC"];
detailVC.delegate = self;
detailVC.userInfo = #"YOUR DATA";
[self presentViewController:detailVC animated:YES completion:nil];
To return you can do this in your detail VC..
[self dismissViewControllerAnimated:YES completion:nil];
I am trying to open a modalview from a view like that,
SignupViewController *signUpView = [[SignupViewController alloc] initWithNibName:#"SignupViewController" bundle:nil];
[signUpView setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
self.parentViewController.view.transform = CGAffineTransformMakeScale(1.3, 1.3);
self.parentViewController.view.alpha = 0;
[UIView animateWithDuration:.35 animations:^{self.parentViewController.view.alpha = 1.0; self.parentViewController.view.transform = CGAffineTransformMakeScale(1, 1);}];
[self presentModalViewController:signUpView animated:YES];
After login i am closing the modalview and redirecting to anther view, but the parentview is still there,
[self dismissViewControllerAnimated:YES completion:^{
ToolsViewController *gototoolpage = [[ToolsViewController alloc] initWithNibName:#"ToolsViewController" bundle:nil];
[self.navigationController pushViewController:gototoolpage animated:YES];
}
How to dismiss the parentview also. Any idea
You code looks a little confused. What do you intend by references to parentViewController? Check the docs - it is the containing viewController, not the previous or presenting viewController. In a NavigationController context this would be the UINavigationController. In a modal view context there is no parentViewController, but there is a presenting ViewController. I am not sure what you intend by all of those calls to self.parentViewController.
In any case you should really be sending the dismiss request back to your presenting viewController via a delegate so that it is completely clear where the pushViewController message is being passed from and to.
In the header file of your signUpViewController declare a protocol:
#protocol SignUpViewControllerDelegate
- (void) dissmissSignUpVC;
#end
then in your presentingViewController, after
SignupViewController *signUpView = [[SignupViewController alloc] initWithNibName:#"SignupViewController" bundle:nil];
add
[signUpView setDelegate:self];
and implement the delegate method with the same code you now have in your completion block:
- (void) dissmissSignUpVC {
ToolsViewController *gototoolpage = [[ToolsViewController alloc]
initWithNibName:#"ToolsViewController" bundle:nil];
[self.navigationController pushViewController:gototoolpage animated:YES];
}
In signUpView invoke the delegate's method to dismiss:
[[self delegate] dissmissSignUpVC];
Watch out for those stacked animations, I suspect that only the first will be performed (i.e. gototollpage animated:YES might as well be gototoolpage animated:NO)
Perhaps anyway you should reconsider your logic. I imagine the user might have a confusing experience if you do this under-the-hood manipulation of viewControllers. Better that there is a UI control for the user to navigate to toolsViewController so they understand where they are?
I got multiple viewcontrollers in my project. The first viewcontroller is called when the application starts and it presents a login screen. When the credentials are correct and the user logs in, the modalview is dismissed. and another viewcontroller is instantiated like this:
[self dismissModalViewControllerAnimated:NO];
Form *formcontroller = [[Form alloc] init];
[self presentModalViewController:formcontroller animated:YES];
When my other viewcontroller is presented the old one disappears. On the top of my secondviewcontroller i got an logout button, wich does exactly the same, so it dismisses the current viewcontroller and calls another like this:
-(IBAction)logOut:(id)sender{
[self dissmissModalViewControllerAnimated:NO];
}
And in my viewdiddisappear:
-(void)viewDidDisappear:(BOOL)animated{
Postform3ViewController *logincontroller = [[Postform3ViewController alloc] init];
[self presentModalViewController:logincontroller animated:YES];
}
The problem is:
When i push the logout button, and i return back to the logincontroller. The Credentials are still filled in. So my conclusion is that the first viewcontroller stays in memory. What am i doing wrong?
Edit:
I did find my own solution. I was profiling my application, and couldn't find any memory leaks. So i decided everything is released. Then i thought that i was able to set everything to empty myself. I did that in the viewDidAppear method like this:
-(void)viewDidAppear:(BOOL)animated {
gebruikersnaam.text = #"";
wachtwoord.text = #"";
[self.activeTextField resignFirstResponder];
[super viewDidAppear:animated];
}
Well first of all when you are using presentModalViewController and pushViewController the VC is retained so you should always release it after you have presented or pushed it.
Secondly in the third block of code it looks like you are creating a logincontroller but presenting a formcontroller. Perhaps you want to be presenting the VC you had just created:
[self presentModalViewController:logincontroller animated:animated];
Edit 0: For your code, in the first block, release like this:
Form *formcontroller = [[Form alloc] init];
[self presentModalViewController:formcontroller animated:YES];
...
[self dismissModalViewController:formcontroller animated:YES];
[formcontroller release];