UIModalPresentationFormSheet dismiss event for Preferences in iOS - ios

I am doing Preferences feature with UIModalPresentationFormSheet with following code in iPad.
self.preferencesViewController = [[PreferenceViewController alloc] initWithNibName:#"PreferenceViewController" bundle:nil];
self.preferencesViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:self.preferencesViewController animated:YES];
When i save preferences and dismiss view controller with
[self dismissModalViewControllerAnimated:YES];
But my preferences is not change.
i write my check preferences coding in viewWillAppear , however viewWillAppear event is not work with UIModalPresentationFormSheet.
I am fine when i use with
self.preferencesViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:self.preferencesViewController animated:YES completion:nil];
Where can i check event for UIModalPresentationFormSheet?
Thanks for your help.

The standard way to get information back to a controller that created you, is to use a delegate protocol. Your preferenceViewController should define a delegate protocol, and the presenting controller should set itself as the delegate before it presents the preferences controller. When you initiate the save of the preferences, PreferenceViewController should send it's delegate a message saying that it's finished and should be dismissed. In the implementation of that delegate method in the presenting controller, it can then read the preferences from where you saved them, and dismiss the PreferenceViewController.

Related

Can't dismiss alerts programmatically in Mac Catalyst?

I'm showing an alert like this:
self.connectingAlert = [UIAlertController
alertControllerWithTitle:#""
message:NSLocalizedString(#"CONNECTING", nil)
preferredStyle:UIAlertControllerStyleAlert];
[self.connectingAlert addAction:[UIAlertAction
actionWithTitle:NSLocalizedString(#"BUTTON_CANCEL", nil)
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
[self cancelRequest];
}]];
[self presentViewController:self.connectingAlert animated:TRUE completion:nil];
Then later I want to dismiss the alert programmatically like this:
[self dismissViewControllerAnimated:FALSE completion:nil];
The dismiss code works fine in iOS, but does nothing in Mac Catalyst. This might have something to do with the fact that alerts are presented as a part of the app window, sort of outside of the app, and the presentation style is ignored. But I would expect the dismiss method to still affect the Mac alerts.
I tried this to make sure everything is hooked up correctly:
UIViewController *test1 = self.connectingAlert.presentingViewController;
UIViewController *test2 = self.connectingAlert.presentingViewController.presentedViewController;
test1 returns the navigation controller that the view controller is part of, which seems odd, but it does the same thing on iOS. test2 returns my alert. Just to make sure, I tried this code, but it doesn't work either:
[self.connectingAlert.presentingViewController dismissViewControllerAnimated:FALSE completion:nil];
Does anyone have experience with this? I don't see anything about it in the documentation.
It turns out that while you're supposed to send the dismiss message to the presenting (parent) view controller...
[self dismissViewControllerAnimated:FALSE completion:nil];
...I have to send the dismiss message to the alert instead, and then it dismisses:
[self.connectingAlert dismissViewControllerAnimated:FALSE completion:nil];
The documentation for dismissViewControllerAnimated says:
The presenting view controller is responsible for dismissing the view
controller it presented. If you call this method on the presented view
controller itself, UIKit asks the presenting view controller to handle
the dismissal.
I think what this means is that Mac Catalyst is doing something funny with the connection between the presenting and the presented view controller. If I check self.presentedViewController, that gives me the UIAlertController. But if I call self dismiss dismissViewControllerAnimated..., nothing happens, as if there is no presented view controller. But if I call self.connectingAlert dismissViewControllerAnimated..., the dismiss method somehow finds its way to the real presenting view controller. I'll report this as a bug to Apple.
Meanwhile, I'm happy to have a workaround.

Error when calling the controller iOS

please help to understand the difficult situation.
I realized the Pop Up Window, the way has been described here
Then, in this window, I decided to implement a sample photo from the library, but when you open a new controller may receive the following warning:
Presenting view controllers on detached view controllers is discouraged <PopUpViewController: 0x7fbb405f4e90>.
The sample photo is implemented as follows:
picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = NO;
[picker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self presentViewController:picker animated:YES completion:nil];
try this:
[self.view.window.rootViewController presentViewController:picker animated:YES completion:nil];
I think you are presenting your picker in your viewDidAppear method.
If this is so, then that is the reason for the warning...
Please write another method that will present our picker and then perform it with delay.
[self performSelector:#selector(yourMethod)
withObject:nil afterDelay:0.0];
This will let your presentingController load completely before it presents another one.
I hope this helps..
EDIT
The problem is, you are presenting the picker, much before your action sheet is dismissed
EDIT 2
Also instead of actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex, use this method for getting clicked Index -
- actionSheet:didDismissWithButtonIndex:
Perhaps you need to add your popup window as a child controller using addChildController to the controller you show it from so that it is not detached from a view hierarchy?
Also you could try: Another option:
[self.parentViewController presentViewController:picker animated:YES completion:nil];
I noticed this on another thread as a solution. Warning :-Presenting view controllers on detached view controllers is discouraged
In your case, parentViewController may well be nil.
Edit After Seeing Code:
After looking at the code, the problem seems to be as follows:
1) The popup mechanism is using an instance of a UIViewController to create a layout, but you are not actually using the view controller at all. The popup mechanism (showInView:withImage:withMessage:animated:) is extracting the view from the controller and adding it into the view hierarchy of the controller asking for the popup. So using code from this popup controller instance which calls [self presentViewController...] is presenting a modal controller from a controller which is not actually being used. This is where the error is coming from I believe. You need to do all alerts and modal presentations from the original controller OR pass in the controller to use.
2) The original article mentions that because only the container view of the controller is used, you need to keep a strong reference to it when you create it. So you should have:
self.popViewController = [[PopUpViewController alloc] initWithNibName:#"PopUpViewController" bundle:nil];
Solution:
I would extend the showInView... method to pass in the controller which owns the view the popup is being spliced into. Then use this controller to present any modal controllers. So change:
- (void)showInView:(UIView *)aView withImage:(UIImage *)image withMessage:(NSString *)message animated:(BOOL)animated
to
- (void)showInController:(UIViewController *)aController inView:(UIView *)aView withImage:(UIImage *)image withMessage:(NSString *)message animated:(BOOL)animated
Store the controller reference passed in a property in your PopUpViewController class then use this property to call presentViewController...

Going from a Storyboard to Nib and back again

Ok, I'm still pretty new; so, please bear with me.
I'm creating a custom app for a friend that displays a list of work orders in a table view. Clicking on a work order brings them to a detail view. In the detail view, there is a button that uses a push to present another screen called completion view. From the completion view, they click a button that uses the following code to present a nib for signature capture.
SigScreenViewController *sigScreenViewController=[[SigScreenViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
[self presentViewController:sigScreenViewController animated:YES completion:nil];
The signature screen uses: https://github.com/jcmontiel/SignatureViewExample for capturing the signature and does it well. I have a button that completes the transaction and sends it back to the table view list.
My problem is that I cannot create a button that will return me to the completion view in the storyboard.
I've tried the following in a button:
[self dismissViewControllerAnimated:YES completion:nil];
or
[self.navigationController popViewControllerAnimated:YES];
I'm open for any suggestions on how I can do it.
Thanks in advance!
Have you tried having the UIViewControllers embedded in a navigation controller ?
Are you pushing from a UIViewController in UIStoryboard to a NIB file?
If so check out this sample project that pushes from storyboard to a NIB:
// in a navigation controller
// to load/push to new controller use this code
// this will be next screen
DetailsViewController *detailsViewController = [[DetailsViewController alloc ]init];
[self.navigationController pushViewController:detailsViewController animated:YES];
// to go back or pop controller use this
// now it will send back to parent screen
[self.navigationController popViewControllerAnimated:YES];

Switching two view controller, back function not working

im have two view controller UserListView and UserProfileView!
in UserListView view controller i'm have a button for swtich to UserProfileView and here is code.
UserListView.m - Click Action
- (IBAction)SettingClick:(id)sender
{
UserList *UserProfile = [self.storyboard instantiateViewControllerWithIdentifier:#"UserProfileView"];
[self presentViewController:UserProfile animated:YES completion:nil];
}
And code working fine, when user switch to profile (UserProfileView) have a close button back to UserListView and here is code.
UserProfileView.m - Close click action
- (IBAction)CloseClick:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
UserProfile *UseList = [self.storyboard instantiateViewControllerWithIdentifier:#"UserListView"];
[self presentViewController:UseList animated:YES completion:nil];
}
in this code i will using [self dismissViewControllerAnimated:YES completion:nil]; to close UserProfileView view controller for low ram usage and it work.
But affter i close UserProfileView i want to open this view controller again and it do not work, UserProfileView not showing again??
i using xcode 5 and building an App for ios 7, please help.
Thanks for your time.
If I understand correctly, when you call SettingClick: your app is displaying a UserList. So, when you dismiss a view controller presented on top of it, you should go back to UserList without the need for presenting it again. So you can try with:
- (IBAction)CloseClick:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
This will work unless you had originally presented UserList as well. In this case, UserList will be dismissed with the top controller. In this case, you can delay presenting a second time UserList after dismissing UserProfile, and it should work.
In the latter case, I would suggest you to use a navigation controller instead of simply presenting your controllers like you are doing. As you see, it is not really straightforward and you will get into catches of any kind. Presenting a controller works ok when you present just one controller at a time. On the other hand, if you instantiate a UINavigationController, this will handle the controllers' hierarchy for you.
use this -
- (IBAction)CloseClick:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
This will return to your previous view when u click that button that has been linked with this action

How can to go back to previous view programmatically without UINavigationController?

How can to go back to previous view programmatically without UINavigationController, because all examples that I have found use UINavigationController ?
I am making view for sending feedback and I would like to use this view in many more apps.
If I use UINavigationController than app need to have UINavigationController to use my view for sending feedback.
Is this possible to do and how ?
This is code how I show my view for sending feedback:
- (IBAction)showFeedbackView:(id)sender {
WOC_FeedbackViewController *feedbackView = [[WOC_FeedbackViewController alloc] init];
[self presentViewController:feedbackView animated:YES completion:nil];
}
Use this to go back
[self dismissViewControllerAnimated:YES completion:nil];
Depending on what your project works (Storyboards or XIB) you can use presentViewController. But thats when you keep a reference on your last viewController's identifier.
If you know the ID of your viewController NSString *yourID;
1) Init your viewController
For storyboard
UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:yourID];
For XIB
UIViewController *vc = [UIViewController alloc]initWithNibName:yourID bundle:nil];
2) Presenting your ViewController
[self presentViewController:vc animated:YES completion:nil];
P.S This is a way to do this, but you should use navigationController because you can keep memory of a viewController on stack so when you need to access it again, you can access it faster. In other words, UINavigationController is applied in every iOS Application you see on App Store.
In Swift, you can use following line of code to go back to previous view controller without navigation controller:
self.dismissViewControllerAnimated(true, completion: nil)

Resources