I'm halfway through implementing a very basic 'Add Contact' Button. I am calling the 'Add View' using the code (via a linked UIButton, that works) :
- (IBAction)showAddContact {
NSLog(#"Hit showAddContact");
ABNewPersonViewController *newPersonViewController = [[ABNewPersonViewController alloc] init];
addContactNavController = [[UINavigationController alloc] initWithRootViewController:newPersonViewController];
[self presentModalViewController:addContactNavController animated:YES];
}
and then I have also set the delegate resonse of:
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person {
NSLog(#"Hit newPersonViewController");
//ABContact *contact = [ABContact contactWithRecord:person];
[self.navigationController popViewControllerAnimated:YES];
}
in my header I have set:
#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#interface test2ViewController : UIViewController <ABNewPersonViewControllerDelegate> {
UINavigationController* addContactNavController;
}
- (IBAction)showAddContact;
#end
I have added the frameworks Addressbook and AddressBookUI.
The add dialog box comes up as expected, I can edit the contact, but I am not able to remove the modal View Controller from the view.
I have even duplicated the problem in a simple test project available here:link text
What am I missing?, I bet it is something extremely simple.
Thanks #norskben
Couple of problems:
You should release the ABNewPersonViewController after presenting it.
You present the ABNewPersonViewController as a modal dialog with presentModalViewController: but you remove it from the screen as if it was pushed on a UINavigationController with popViewControllerAnimated:. Instead you should either push and pop, or present and dismiss. (If you don't know what this means, read a little int he View Controller documentation)
Even though you implement the ABNewPersonViewControllerDelegate protocol, you never set the delegate property of the ABNewPersonViewController.
Related
I am having issues with the back button not showing up on the SettingsViewController. The navigation bar does show up when the view is pushed, but no back button.
I am creating this inside a view controller, which is not a navigation controller. Any ideas or suggestions on what is actually going on here.
- (void)viewDidLoad
{
self.title = #"Settings";
}
- (IBAction)showSettingsModal:(id)sender
{
SettingsViewController *settingsViewController = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:settingsViewController] autorelease];
[self presentModalViewController:navController animated:YES];
[settingsViewController release];
}
You are creating a new navigation stack. You will need to add your own Back button and set the action of that to a delegate method on the calling VC to dismiss it.
UPDATE:
There seems to be lots of confusion about where and how to dismiss ModalViewControllers. The wrong thing to do in most cases is to call the Dismiss method from the Modal VC itself if you are wanting the parent to act on that dismissal. Instead, use delegation. Here is a simple example:
ModalViewController.h:
#protocol ModalViewControllerDelegate
-(void)dismissMyModalVC;
#end
#interface ModalViewController : UIViewController {
id < ModalViewControllerDelegate > delegate;
}
#property (nonatomic, retain) id < ModalViewControllerDelegate > delegate;
// The rest of your class properties, methods here
ModalViewController.m
#synthesize delegate;
...
// Put in the Method you will be calling from that Back button you created
[delegate dismissMyModalVC];
CallingViewController.h:
#import "ModalViewController.h"
#interface CallingViewController : UIViewController
<ModalViewControllerDelegate>
// Rest of class here
CallingViewController.m:
ModalViewController *mvc = [[ModalViewController alloc] initWithNibName:#"ModalViewController" bundle:nil];
mvc.delegate = self
[self presentModalViewController:mvc animated:YES];
...
// The ModalViewController delegate method
-(void)dismissMyModalVC {
// Dismiss the ModalViewController that we instantiated earlier
[self dismissModalViewControllerAnimated:YES];
That way the VC gets dismissed properly from the controller that instantiated it. That delegate method can be modified to pass along objects as well (like when you are finished logging a user in, etc)
SettingsViewController does not have a back button because it is at the bottom of stack. If you want a button to dismiss the modal dialog, you will have to add it yourself.
you can try this
UIBarButtonItem * backButton = [[UIBarButtonItem alloc]initWithTitle:#"Back"style:UIBarButtonItemStylePlain target:self.navigationItem.backBarButtonItem action:#selector(dismissModalViewControllerAnimated:)];
You are presenting your new controller as modal view controller. Modal controller presents its topmost. You should:
[self.navigationController pushViewController:navController animated:YES];
to push view controller onto the stack, and then you will see Back button.
Read Apple documenation on presenting view controllers:
https://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html
EDIT Didn't see that the calling view controller is not part of the navigation controller. In that case, you will have to create back button manually, and set it as a left bar navigation item.
All I need is to view a UIView controller in same storyboard file manually with code. I use storyboard to make all forms and connections. My application starts in navigation controller, which provides me access to UIView (LoginViewController) and then it goes to tab bar controller, which provides 4 UIViews. According to every UIView I have .h and .m files. I know about segue method, it is simple, but I need manual method. Maybe I am doing something wrong.
I was trying to use this method for pushing view controller in IBAction:
[self.view pushViewController:LoginViewController animated:YES];
But it makes an error:
Unexpected interface name ‘LoginViewController’: expected expression
It took a lot of time to figure out what is wrong, but I had not succeed.
Here is my RollEnemyController.m file:
// RollEnemyController.m
#import "RollEnemyController.h"
#import "LoginViewController.h"
#implementation RollEnemyController;
#synthesize AttackButtonPressed;
- (IBAction)AttackButtonPressed:(id)sender {
LoginViewController* controller = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[self.view pushViewController:controller];
}
#end
And this is header file:
// RollEnemyController.h
#import <UIKit/UIKit.h>
#interface RollEnemyController : UIViewController
- (IBAction)RollButtonPressed:(id)sender;
#property (weak, nonatomic) IBOutlet UIButton *AttackButtonPressed;
#end
I'm guessing that you are using a UINavigationController. Then you can simply do like this:
LoginViewController *controller = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
Update:
If you are using a UIStoryboard, you can set the identifier of your new viewcontroller, and then push it onto your navigationController. To set the identifier, choose your view, open the Attributes Inspector, and set the identifier ("LoginIdentifier" in my example). Then you can do this:
LoginViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"LoginIdentifier"];
[self.navigationController pushViewController:controller animated:YES];
As a sidenote, I see that you are using capital characters for your methods. You should probably try to avoid that, and instead use lowered first-characters in your method names. And since you say you are learning Objective-C, you should check out this awesome thread here on SO: link.
Update 2:
Here is a zip file with a project showing how to do this. :-)
hello try to use this code
Storyboard put ID = "xxx * Name Desire"
mark use StoryboarID
UIStoryboard * storyboard = self.storyboard;
DetailViewController * detail = [storyboard instantiateViewControllerWithIdentifier: # "xxx * Name Desire"];
[self.navigationController pushViewController: detail animated: YES];
In this statement:
[self.view pushViewController:LoginViewController animated:YES];
it seems you are trying to push a class. You should push an object, your actual controller:
LoginViewController* controller = [[LoginViewController alloc] init...];
[self.view pushViewController:controller animated:YES];
this will at least compile, and if all the rest is fine, also give you the second controller.
EDIT:
I missed one point. You are pushing the view controller on to a view. That makes no sense, you should push the controller on to the navigation controller:
<AppDelegate> *del = (AppDelegate*)[UIApplication sharedApplication].delegate;
[del.navigationController pushViewController:controller animated:YES];
This is true, at least, if you created your project from the Navigation-based template (which creates an application delegate with a reference to the navigation controller). Otherwise, please provide details about how you create the navigation controller.
You mentioned in a comment that you're using UIStoryboard. Are you aware of UIStoryboardSegue? All you have to do it control-drag from the button to the next view controller to establish a segue. Then you can choose the type of transition. Be aware that your view controllers need to be part of a UINavigationController in the storyboard to perform a "Push" animation.
So, I have a tabbarcontroller, and I pass a notification to dismissModalViewController when a particular tabBarItem is touched.
It is working well and the modal View Controller is dismissed. But I want to change it in a particular way, and it does not work as I expect it to...
I have the observer initialized before the notification is posted. These are the tabBarItems -
NSArray *viewControllerss = [[NSArray alloc] initWithObjects: myProfileDataViewController,
sampleViewController,reminderInfoViewController, nil];
[self.tabBarContr setViewControllers:viewControllerss animated:YES];
self.tabBarContr.selectedIndex = 2;
I send a notification on the viewWillAppear of sampleViewController and when I choose that tabBarIcon, it dismisses the TabBarController.
BUT I want the sampleViewController to be on the left most of the UITabBar.
And so I add it like
NSArray *viewControllerss = [[NSArray alloc] initWithObjects: sampleViewController,
myProfileDataViewController, reminderInfoViewController, nil];
THIS DOES NOT DISMISS TAB BAR CONTROLLER.
Note: Please see the order in which NSArray is initialized.
The notification is posted in the viewWillAppear ofsampleViewController` and observer in the respective view controller which presents the modal view controller
Could you put a NSLog right before you post the notification?
See if you get any output when the app loads.
EDIT: Adding onto the answer based on your response
In your sampleViewController could you try this:
Make it conform to the UITabBarControllerDelegate. Your sampleViewController class interface should be something like this:
#interface SampleViewController : UIViewController <UITabBarControllerDelegate>
Then in the .m of your sampleViewController, in the viewDidLoad, set the delegate to be the sampleViewController (self in this case)
-(void) viewDidLoad
{
[super viewDidLoad];
// Assuming you have a reference to your tabBarController somewhere
[self setDelegate:self]; // try this line or the line below
// [[self tabBarController] setDelegate:self];
// The rest of your drawing code here
}
Now implement the delegate method somewhere inside the sampleViewController .m file.
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
// I've included this to see if this method actually gets called or not.
NSLog(#"Dismissing modal view controller");
// check to make sure sampleViewController tab was pressed by checking
// the class type of the viewController parameter being passed in
if ([viewController isKindOfClass:[SampleViewController class]]
{
// I assume you have a pointer reference to that modal view controller
// you want to dismiss
[self dismissModalViewController:theUnwantedViewController animated:YES];
}
}
See if that works.
I have created a new application using the View Based Application Template in xCode.
My first view, which displays on loading the app, is a button based menu. One of the buttons (Make) should load a new navigation stack using a NavigationViewController. There are other buttons that when implemented will do other things outside of NavigationViewController's scope.
I would like to be able to click Make and open and display a new navigation controller.
From ViewController.m:
-(IBAction)makeStory:(id)sender{
NSLog(#"makeStory:");
navController = [[UINavigationController alloc] init];
makeStoryTableViewController = [[MakeStoryTableViewController alloc] initWithNibName:#"MakeStoryTableViewController" bundle:nil];
[navController pushViewController:makeStoryTableViewController animated:YES];
}
I have created a NavigationViewController in the opening ViewController.h file:
#import <UIKit/UIKit.h>
#import "MakeStoryTableViewController.h"
#interface StoryBotViewController : UIViewController {
UINavigationController *navController;
MakeStoryTableViewController *makeStoryTableViewController;
}
- (IBAction)makeStory:(id)sender;
#end
I know I'm missing something because when I call pushViewController nothing happens - I think that somehow I have to attach the NavigationViewController to the ViewController that makeStory: is in.
For reference, my app delegate header declares the view controller in the #implementation as follows:
UIWindow *window;
StoryBotViewController *viewController;
with the appropriate #synthesize in the .m of the app delegate
#synthesize window;
#synthesize viewController;
How do I push a NavigationStack on from my opening view controller?
Please forgive me if the question is a little vague, I'm happy to provide more information if you need it. It's my first time questioning on stackoverflow and I'm obviously a bit of a newbie with the iPhone SDK.
you had it almost. But you forgot to add the NavigationController to your view.
[self.view addSubview:navController.view];
Add this in your IBAction.
EDIT:
but much likely this is not what you want, because you can't navigate back to your very first viewController. If you want to navigate back to the first viewController set up your project like in the navigation-based template. You can to this programmatically to:
Move all UINavigationController stuff from the header file of the viewcontroller to the app delegate header. And change your app delegate implementation to something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
navController = [[UINavigationController alloc] initWithRootViewController:viewController];
// Add the view controller's view to the window and display.
// [window addSubview:viewController.view];
[window addSubview:navController.view];
[window makeKeyAndVisible];
return YES;
}
make sure to release navController in dealloc
then replace your IBAction with something like this:
- (IBAction)makeStory:(id)sender {
makeStoryTableViewController = [[MakeStoryTableViewController alloc] initWithNibName:#"MakeStoryTableViewController" bundle:nil];
[self.navigationController pushViewController:makeStoryTableViewController animated:YES];
}
if you don't like to display the navigationbar in your first viewcontroller hide it, but make sure to unhide it if you push other items on the stack. self.navigationController.navigationBar.hidden = ...
I am trying to implement a modal navigation controller as described in the Apple iOs Guide: Combined View Controller Interfaces
I have come to the conclusion that I am missing something both obvious and stupid as I simply cannot get anything to display, I get a blank white screen.
Swapping things out I can prove that the view controller that I am using as the navigation controllers RootViewController works fine on it's own (by adding it manually as a view subChild).
Further, implementing addSubView ([self.view addSubview:navController.view]) instead of presentModalViewController seems to work OK.
Can anyone point out my simple error because I am 5 minutes short of kicking my own face :D
header
#import <UIKit/UIKit.h>
#interface BaseViewController : UIViewController {
}
implementation
#import "BaseViewController.h"
#import "ScannedListViewController.h"
#import "ScannedItemViewController.h"
#implementation BaseViewController
- (void)viewDidLoad {
ScannedListViewController *listViewController = [[ScannedListViewController alloc] init];
ScannedItemViewController *itemViewController = [[ScannedItemViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:listViewController];
[navController pushViewController:itemViewController animated:NO];
[self presentModalViewController:navController animated:YES];
[listViewController release];
[itemViewController release];
[navController release];
[super viewDidLoad];
}
The RootControllerView is a basic test TableViewController with the following header
#interface ScannedListViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>
Thank you in advance if your able to help
Why are you presenting something modally in a view controller's viewDidLoad method? I find that odd off the top. Generally you show a modal view controller in response to some action (like tapping a button).
Is there a reason you're showing a navigation controller with a second view controller already pushed on it after the root?
You should have [super viewDidLoad] as the first line, not the last line, of the method.
You do not need to have <UITableViewDelegate, UITableViewDataSource> after UITableViewController because it already adopts those protocols. Remove that bit.