Reputation: 11095
Above is my storyboard. The first view is hooked up to ViewController, and the second isn't connected to anything. I know how to show the second view controller if I had a button on the first. I can click and drag from the button to the second view, creating a segue. However, this time, I have to show the second view controller programmatically inside ViewController.m. For example, in when some function myFunc is called, I want to show the second view controller. Could someone explain how I can do this?
I think I need to know the followings:
Thank you!
UPDATE:
//setSelectedDate is myFunc. It lives inside myView.m, which is a subview of UIView
- (void)setSelectedDate:(NSDate *)newSelectedDate; {
NSLog(@"override worked");
[super setSelectedDate:newSelectedDate];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *firstController = [storyboard instantiateViewControllerWithIdentifier:@"InitialViewController"];
UIViewController *myController = [storyboard instantiateViewControllerWithIdentifier:@"MySecondViewController"];
[firstController presentViewController:myController animated:YES completion:nil];
}
I get the following warning if I do above:
Warning: Attempt to present on whose view is not in the window hierarchy!
and from this post I believe it's because I am doing it in the wrong place. How can I resolve this issue?
**Update 2: I did the following: **
- (void)setSelectedDate:(NSDate *)newSelectedDate; {
[super setSelectedDate:newSelectedDate];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *firstController = [storyboard instantiateViewControllerWithIdentifier:@"InitialViewController"];
[firstController performSegueWithIdentifier:@"GoToSecondViewController" sender:firstController];
The warning is gone, but the view controller is still not showing. Is it because I am calling this inside a View instead of a ViewController?
Upvotes: 1
Views: 143
Reputation: 2130
To avoid tightly coupling these components, here's how I'd do it.
In myView.h
, add a delegate protocol to which your InitialViewController
will conform, and a property of that type to the myView
class:
@class myView;
@protocol myViewDelegate
-(void)datePickerDidChangeValue:(myView*)view;
@end
@interface myView : UIView
@property IBOutlet id<myViewDelegate> delegate;
// ... other members ...
@end
And in its implementation call that delegate method in the setSelectedDate:
method:
-(void)setSelectedDate:(NSDate*)selectedDate
{
_selectedDate = selectedDate;
[self.delegate datePickerDidChangeValue:self];
}
Then, set the delegate property in InterfaceBuilder to be your InitialViewController. Right click on your custom view and then drag from the delegate
outlet to your ViewController:
Then, in InitialViewController.h, set it to conform to the myViewDelegate protocol:
#import "myView.h"
@interface InitialViewController : UIViewController<myViewDelegate>
// ... members ...
@end
and implement that delegate method, something like this, assuming you've set up the identifiers as described in this answer:
-(void)datePickerDidChangeValue:(myView*)view
{
NSDate* theDate = view.selectedDate; // do whatever you want with this value
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:[NSBundle mainBundle]];
UIViewController *myController = [storyboard instantiateViewControllerWithIdentifier:@"MySecondViewController"];
[self presentViewController:myController animated:YES completion:nil];
}
Upvotes: 1
Reputation: 5831
You could do one of the following:
Create a segue in your storyboard by dragging from the firstViewController to the second one. Then give that segue a name (fill the Identifier field, under Attributes inspector on the right pane in Interface Builder). Let's say "GoToSecondViewController".
In your myFunc
method (or function), call
[self performSegueWithIdentifier:@"GoToSecondViewController" sender:nil];
OR
Give your second viewcontroller a storyboard ID. From the interface builder, click on your second viewcontroller. On the right pane under "Identity inspector" fill in the Storyboard ID field. Let's say "MySecondViewController".
In your myFunc
method (or function) do the following:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:[NSBundle mainBundle]]; // or whatever your storyboard is called
UIViewController *myController = [storyboard instantiateViewControllerWithIdentifier:@"MySecondViewController"];
[self presentViewController:myController animated:YES completion:nil]; // present it or push it if you have a navigation controller
Upvotes: 2