Issue while pushing ABNewPersonViewController - ios

I am using AddressBookUI Framework for Adding contact, when I tried to pushing this view controller then cancel and done button not working properly, I don't want to present it
Here is my code
ABNewPersonViewController *abnpvc = [[ABNewPersonViewController alloc] init];
[abnpvc setNewPersonViewDelegate: self];
[self.navigationController pushViewController:abnpvc animated:YES];
I am also tried add as subview rather then pushing it but when I am adding as subview then it was not added
As per comment i have tried like
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:abnpvc];
[self presentViewController:navigation animated:YES completion:nil];
Can anyone help me out why properly not working ?

You can implement that too considering also the other answers and the deprecations to ABNewPersonViewController in iOS 9.
As per your remarks:
cancel and done button not working properly
They are working if you have included the ABNewPersonViewControllerDelegate on interface like this:
#interface ViewController () <ABNewPersonViewControllerDelegate>
Pushing the viewController on navigation stack like this:
ABNewPersonViewController *controller = [[ABNewPersonViewController alloc] init];
controller.newPersonViewDelegate = self;
[self.navigationController pushViewController:controller animated:YES];
And by conforming to the protocol by implementing this method:
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonView didCompleteWithNewPerson:(nullable ABRecordRef)person {
// Trick to go back to your view by popping it from the navigation stack when done or cancel button is pressed
[self.navigationController popViewControllerAnimated:YES];
}
The tricky line is to pop the newPersonController from the navigation stack when either Done or Cancel button are pressed.
Enjoy it

Why can't you just do it as the docs say?
It is recommended that you present a new-person view controller modally.
Use
ABNewPersonViewController *abnpvc = [[ABNewPersonViewController alloc] init];
[abnpvc setNewPersonViewDelegate: self];
[self presentViewController:abnpvc animated:YES completion:nil];
That should work fine.
Edit
On second thought, did you set your delegate correctly and do the implementations get called? I suspect they are not implemented or the delegate is not set correctly.

Apple guideline(IMPORTANT) :: New-person view controllers must be used with a navigation controller in order to function properly. It is recommended that you present a new-person view controller modally.
Add Delegate
#interface ViewController () <ABNewPersonViewControllerDelegate>
Pushing the viewController
ABNewPersonViewController *abnpvc = [[ABNewPersonViewController alloc] init];
[abnpvc setNewPersonViewDelegate: self];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:abnpvc];
[self presentModalViewController:navController animated:YES];
And Now Add Delegate Method
#pragma mark ABNewPersonViewControllerDelegate methods
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
That will work fine.

Related

how to add New UIViewCOntroller Over UiView

I have added subview in a UIViewController and I want a new UIViewController Should be loaded on click of button.
Challenge is I am not able to use button in new UIViewController.
Code which I have write:
DetailsOfDayViewController *aViewController =[[DetailsOfDayViewController alloc] initWithNibName:#"DetailsOfDayViewController" bundle:nil];
aViewController.dateParsing = dateparsing;
[self addSubview:aViewController.view];
This will fix your issue. This is happening because your view controller is being deallocated when you don't have any strong pointers on it.
DetailsOfDayViewController *aViewController =[[DetailsOfDayViewController alloc] initWithNibName:#"DetailsOfDayViewController" bundle:nil];
aViewController.dateParsing = dateparsing;
[self addChildViewController:aViewController];
[self addSubview:aViewController.view];
Another fix will be connecting this view controller to a property:
#property(nonatomic,strong) DetailsOfDayViewController *aViewController;
And change your code like this:
self.aViewController = [[DetailsOfDayViewController alloc] initWithNibName:#"DetailsOfDayViewController" bundle:nil];
self.aViewController.dateParsing = dateparsing;
[self addSubview:self.aViewController.view];
For showing another controller you can following options
1. Add SubView
newViewControllerObj.view.frame = oldViewControllerObj(self).view.frame
[oldViewControllerObj(self).view.newViewControllerObj.view];
2. Present
[oldViewControllerObj(self) presentViewController: newViewControllerObj animated:YES completion:nil];
3. Push using Navigation (For this you already have to set navigation controller as root controller)
[oldViewControllerObj(self).navigationController pushViewController:newViewControllerObj animated:YES];

iOS - how to set a navigation bar item in view controller?

I'm new to Objective-C and I want to add a UINavigationBar on my CatrgoryBIDViewController. I have proceed UIButton in InstructionBIDViewController.m file that should navigate to CatrgoryBIDViewController. Here is the function code:
- (IBAction)proceed:(id)sender {
viewControllercat =
[[CatrgoryBIDViewController alloc]
initWithNibName:#"CatrgoryBIDViewController"
bundle:nil];
UINavigationController *nav =
[[UINavigationController alloc]
initWithRootViewController:self.viewControllercat];
//[self.navigationController pushViewController:viewControllercat animated:YES];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
But it is not setting the UINavigationBar.
You should read the documentation here to understand the way a NavigationController is working. For your case:
If your current ViewController (where your proceed-method is implemented) has a NavigationController (is child of it), you can push another ViewController onto the stack of that NavigationController with
[self.navigationController pushViewController:viewControllercat animated:YES];
In this case you do not need to initialize another NavigationController, but in your CatrgoryBIDViewController in viewWillAppear you need to make the NavigationBar visible if it was not before already with
[self.navigationController setNavigationBarHidden:NO animated:YES];
If your current ViewController does not have a NavigationController, you can not push another ViewController on top of it and can not show the NavigationBar of it (although you can create your own NavigationBar and add it to the View of the ViewController, but without the usual Navigation-behaviour embedded).
If you open your ViewController programmatically (e. g. from the AppDelegate) you are correct to do so by your call:
viewControllercat = [[CatrgoryBIDViewController alloc] initWithNibName:#"CatrgoryBIDViewController" bundle:nil];
UINavigationController *nav=[[UINavigationController alloc] initWithRootViewController:self.viewControllercat];
My apologies - After having reread your question, I am going to tweak my answer some.
-(IBAction)proceed:(id)sender
{
viewControllercat = [[CatrgoryBIDViewController alloc] init];
UINavigationController * nc =
[[UINavigationController alloc] initWithRootViewController:vc];
// We now need to display your detail view but cannot push it.
// So display modally
[self presentViewController:nc animated:YES completion:Nil];
}
The above should result in your DetailViewController - CategoryBIDViewController being displayed on top of your InstructionBIDViewController and it should have a UINavigationController in it.

Instantiate UINavigationController on button action

I have simple application with only one main view, which has 'Settings' button, and settings are tree-grouped, so I wand to present them in navigation controller. And I don't want navigationController in main view, because I don't want navigation bar there.
That's why I don't instantiate navigationController in application: didFinishLaunchingWithOptions:. And when I check self.navigationController in 'Settings' button handler, it returns nil.
So I wrote this: (I use ARC)
- (void)doSettings
{
NSLog(#"%#", self.navigationController); // prints nothing
SettingsViewController *settingsViewController = [SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navigationController = [[UINavigationController alloc] init];
[self.view.window setRootViewController:navigationController];
[navigationController pushViewController:settingsViewController animated:YES];
}
This works, although it pushes settingsViewController without animation (don't know why).
Is this generally the correct way to do - to change rootViewController in the middle of running app?
And if yes - than when I'm done with Settings, I probably need to set rootViewController back to current viewController, as it was before I tapped 'Settings'?
I think you want to create a navigation controller that you will present modally; the following will do:
SettingsViewController* settingsViewController = [[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navigationController = [[UINavigationController alloc] init];
[navigationController pushViewController:settingsViewController animated:YES];
[self presentViewController: navigationController animated: YES completion:nil];
where self here is the view controller you want to trigger the modal view controller from.
since you present modally the navigation controller you can dismiss it within the code source of your settingsViewController by accessing its navigation controller:
[self.navigationController dismissViewControllerAnimated:YES completion: nil];
To answer your question setting the rootViewController is not the correct way. Present the new vc modally through the presentViewController method.
A better way is to build the navigation vc and present it over your main vc (not replace your main vc).
- (void)doSettings
{
NSLog(#"%#", self.navigationController); // prints nothing
SettingsViewController *settingsViewController = [SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController: settingsViewController];
[self presentViewController: navigationController animated:YES completion:^{}];
}
Your main vc might realize (maybe as a delegate) that the settings flow is complete. It can then dismiss the presented navigation controller with:
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
Alternatively, the setting flow could dismiss itself...
// somewhere in the settings vc or a vc it pushes, when we decide settings are done
self.navigationController dismissViewControllerAnimated:YES completion:^{}];
Have navigation in main view and have below line (which will hide navigation bar)
[[self navigationController] setNavigationBarHidden:YES animated:YES];
(I would say have this in viewWillAppear and viewDidLoad both, BUT in viewWillAppear is MUST).
Now in second view, to show navigation bar
[[self navigationController] setNavigationBarHidden:NO animated:YES];
Hope this will solve your problem...

Muiltple Modal UIViewControllers | Dismiss Top Modal UIViewController Only

My UIViewController stack looks as follows:
+------ UIViewController_C (presented)
+---- UIViewController_B (presented)
+-- UIViewController_A (pushed)
When I call -dismissViewController:animated on UIViewController_C, UINavigationController dismisses both UIViewController_C and UIViewController_B together, as per the docs with animation on _C, and none on _B.
What is the most compliant way to dismiss _C only?
try as below
after pushing to UIViewController_A present UIViewController_B as below code.
UIViewController_B *bbp=[[UIViewController_B alloc]initWithNibName:#"UIViewController_B" bundle:nil];
UINavigationController *passcodeNavigationController = [[UINavigationController alloc] initWithRootViewController:bbp];
passcodeNavigationController.navigationBar.hidden=YES;
[self.navigationController presentModalViewController:passcodeNavigationController animated:YES];
[passcodeNavigationController release];
now from UIViewController_B try to present in UIViewController_C as below code.
UIViewController_C *bbp=[[UIViewController_C alloc]initWithNibName:#"UIViewController_C" bundle:nil];
UINavigationController *passcodeNavigationController = [[UINavigationController alloc] initWithRootViewController:bbp];
passcodeNavigationController.navigationBar.hidden=YES;
[self.navigationController presentModalViewController:passcodeNavigationController animated:YES];
[passcodeNavigationController release];
last and final thing on every back button of view controller write below line of code.
[self dismissModalViewControllerAnimated:YES];
if you want more help than comment bellow.
One Solution:
UIViewControllers presented modally are not necessarily deallocated on -dismissViewController:animated.
This means that by passing a reference to UIViewController_A through _B to _C, you can call -presentViewController:animated and -dismissViewController:animated for the respective UIViewControllers via UIViewController_A.
Code:
1. UIViewController_B
- (void) showUIViewController_C {
[self dismissViewControllerAnimated:TRUE completion:^{
UIViewController_C *controller_C = [[UIViewController_C alloc] init];
controller_C.parentController = self;
[self.parentController controller_C animated:TRUE completion:nil];
}];
}
2. UIViewController_C
- (void) dismissUIViewController_C {
[self dismissViewControllerAnimated:TRUE completion:^{
[self.parentController.parentController presentViewController:self.parentController animated:TRUE completion:nil];
}];
}
Where I am using *parentController as the naming convention for whatever class your previous UIViewController on the stack may be.
It dips back to UIViewController_A briefly because I am calling -dismiss and -present in the completion block, though that actually looks rather fun.

iOS presented UINavigationController gets dismissed after it performs a popViewController

In my app i present a UINavigationController modally with a UIViewController as its rootViewController. I do it in form style. I added a second UIViewController which is also in form style and i can push to it fine. However when i perform a popViewController action after the second UIViewcontroller gets popped onto the first, the whole modally presented UIViewController gets dismissed. However i don't perform any dismissing and the dismissing function doesn't get triggered by accident either.
Any ideas why it's happening?
Sincerely,
Zoli
EDIT:
That's how i'm presenting the modal viewcontrollers with a navcontroller:
if(!welcomeScreenAlreadyPresented) {
welcomeScreenViewController = [[WAWelcomeViewController alloc]init];
}
welcomeScreenNavController = [[UINavigationController alloc]initWithRootViewController:welcomeScreenViewController];
[welcomeScreenNavController setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];
[welcomeScreenNavController setModalPresentationStyle:UIModalPresentationFormSheet];
[welcomeScreenNavController setNavigationBarHidden:YES animated:NO];
[self.navigationController presentViewController:welcomeScreenNavController animated:YES completion:nil];
That's how i'm navigation in WAWelcomeViewController.m
registerViewController = [[WARegisterViewController alloc]init];
[self.navigationController pushViewController:registerViewController animated:YES];
And in WARegisterViewController.m that's how i pop back
[self.navigationController popViewControllerAnimated:YES];
What you need to do is put the viewController you want to push inside another UINavigationController.
registerViewController = [[WARegisterViewController alloc]init];
UINavigationController *modalNavigationController = [[UINavigationController alloc] initWithRootViewController:registerViewController]; // autorelease if you are not using ARC
[self presentViewController:navController animated:YES completion:^{}];
You might want to add the modalNavigationController as a property to later call popViewControllerAnimated: on it.

Resources