Button present a navigationViewController with a different embed viewContoller in the container - ios

I have 3 different buttons which upon touch present the same UINavigationViewController with a container.
However, each button represents which view controller will be embed at the container.
How can I embed the necessary viewController by code?

what you can do is use an identifier which would be assigned to your various viewController as storyboardID
such as fisrtVC, SecondVC, thirdVC
the depending upon whichButton is pressed just set the identifier and use this identifier when
you want to push the controller such as
for example
while you push the navigation viewController just pass the storyboard Identifier such as
Declare a NSString *identifier;
-(IBAction)firstButtonClicked{
identifier=#"firstVC";
//pass this identifier to your navigationController
}
similarly for other Controllers
When you push the navigation controller make sure to pass this identifier along now depending upon the value you can initiate the controller on you VC as
on ViewDIdApppear:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
NSString* viewType = passedIdentifier
UIViewCOntroller* viewController = [storyboard instantiateViewControllerWithIdentifier:viewType];
Load this "viewCOntroller in your ContainerView"

You should implement prepareForSegue method:
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
id is your button that will fire segue. You do segues by drugging and drop in storyboard. Put an if statement in this method and tell your UIViewController which UIView to load in container. You can pass data like this:
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
Second snippet taken from this answer.
Update.
To load different UIView in container put if statement into viewWillApper method.
This method firing earlier than viewDidLoad. If statement must check some property that tell what UIView to init. You setting up this property in prepareForSegue.
It will look like this:
if (self.viewToLoad == 1)
{
self.dynamicView = MyCustonUIViewNumberOne *view = [MyCustonUIViewNumberOne alloc] init];
}
Update 2.
Or you can do it dynamically like in this answer:
if (self.viewToLoad == 1)
{
// Replacing with your dimensions
CGRect frame = CGRectMake(x, y, width, height);
MyCustonUIViewNumberOne *dynamicView = [[MyCustonUIViewNumberOne alloc] initWithFrame:frame];
[self.container addSubview: dynamicView];
} else {
// Init other view
}
The container property:

Related

Perform Segue With Identifier for already Instiated View Controller

I'm trying to use a custom segue (at bottom) to present a view controller modally with a blur view. I need to instantiate the view controller with properties before I present the view controller.
Instating the VC works great when I am using pushVC, but when I use perform segue with identifier, I don't see an option to choose an already instantiated VC.
CustomViewController* VC = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:#"customVC"];
[self.navigationController performSegueWithIdentifier:#"blurSegue" sender:self];
How can I perform the custom segue and force it to use the view controller I allocated (called VC above)?
https://github.com/AlvaroFranco/AFBlurSegue
I need to instantiate the view controller with properties before I
present the view controller.
Why do you have to instantiate CustomViewController before triggering the segue. That shouldn't be necessary, if you need access to a property of CustomViewController before it's shown, you can set it in prepareForSegue.
Try this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"blurSegue"]) {
CustomViewController *customViewController = (CustomViewController *)segue.destinationViewController;
customViewController.propertyToSet = XXX; // set the property here
}
}
Ah, by the way, instead of
[self.navigationController performSegueWithIdentifier:#"blurSegue" sender:self];
just use:
[self performSegueWithIdentifier:#"blurSegue" sender:self];

creating push segue programatically and prepareforsegue method

i have a button that is created programmatic and i need to perform a segue on click that will send data with prepareForSegue, but this code wont trigger it.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UIViewController * vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"AddToCalendarViewController"];
[self.navigationController pushViewController:vc animated:YES];
i have tried this:
[self performSegueWithIdentifier:#"addToCalendar" sender:self];
but since the button is created grammatically i don't have any segue identifier to call, and using the following to create it did not work
UIStoryboardSegue * segue = [[UIStoryboardSegue alloc] initWithIdentifier:#"addtoCalendar" source:self destination:vc];
UIStoryboardSegue must not be created programmatically. Create a segue by connecting your view controller to the destination view controller in the storyboard and put its identifier to #"addToCalendar" (always in the storyboard). Then call it as you are already doing.
If you don't have an actual storyboard segue to call when the button is pressed, then you need to call addTarget:action:forControlEvents, where action is a selector to the method on target to be called.
Specifically, you first need to create a method to push the destination view controller, like so:
- (void)addToCalendar {
DestinationiewController * vc = [[DestinationViewController alloc] initWithNibName:#"destinationViewController" bundle:nil;
[self.navigationController pushViewController:vc animated:YES];
}
and then in your source view controller's viewDidLoad (or wherever you're programmatically instantiating the button), you need to add
[self.button addTarget:self action:#selector(#"addToCalendar") forControlEvents: UIControlEventTouchUpInside];
which will call the addToCalendar method you defined above.

TapGestureRecognizer on UIToolbarButton doesn't work

I have a UIToolbarButton which has a UIButton to hold the image. Now, when I click on this UIToolbarButton, I want to open another view in the current view.
My Code :
- (IBAction)btnNowPlaying:(id)sender
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(openPlaying:)];
[self.view addGestureRecognizer:tap];
}
- (void)openPlaying:(UIGestureRecognizer *)sender
{
NewMainViewController *vc = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"Center"];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController * npvc = [storyboard instantiateViewControllerWithIdentifier:#"NowPlayingVC"];
[vc.containerView addSubview:npvc.view];
}
This action, btnNowPlaying is on the UIButton.
It sounds like you simply want to navigate from one view controller to another. Just control-drag from your bar button item to the view controller you'd like to navigate to in your storyboard. Then, click the segue between the two view controllers and set its identifier in the Attributes inspector. After that, all you need to do is implement prepareForSegue::
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"THE_IDENTIFIER_YOU_ENTERED_IN_THE_ATTRIBUTES_INSPECTOR"]) {
if ([segue.destinationViewController isKindOfClass:[NEWViewController class]]) {
NEWViewController *vc = (NEWViewController *)segue.destinationViewController;
// Any preparation you need to do for next view controller
vc.someProperty = someValue;
}
}
}
It's a little strange to open a new view controller inside the current view controller. Why not just segue to it?
Another option would be to alloc-init a UIView instead of a view controller and simply addSubview:.
First of all, you can use default UIBarButton item with Custom style and setter Image property instead of creating UIButton.
You don't need to create additional gesture recogniser. If you have connect IBAction with button in Interface Builder, you can put your transition code inside btnNowPlaying method.
Another way is to create IBOutlet, connect it with your button and create UIGestureRecognizer in - (void)viewDidLoad method.

Set segue identifier programmatically

Lets say i have a ViewController with a textField and a button.
I want to use an unwind segue so i could get the information of the textField to my other viewController after i clicked the button.
I want to use the PrepareForSegue method so i could save the text from the textField in a property before i"m "unwiding".
How do i set an identifier to my segue manually? If it was a bar Button item i could use the IB to set the identifier ( to "Save" for example) and then use it. This is not the case, just a regular button.
It is not possible to create segues programmatically. They cannot exist without storyboards.
See this question.
You can easily add a segue programmatically (without using storyboards). In the source view controller header file:
#property (nonatomic, strong) UIStoryboardSegue *segue;
In the source view controller implementation file, set up the segue property accordingly:
self.segue = [UIStoryboardSegue segueWithIdentifier:[NSString stringWithFormat:#"%lu", indexPath.item] source:self destination:[PlayerViewController sharedPlayerViewController] performHandler:^{
// Insert whatever; nothing is needed for a basic segue
}];
Also, in the source view controller, add the destination view controller set up and transition in the prepareForSegue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// The code in this method both sets up the destination view controller and transitions to it; you could optionally do set up here only, and then transition in an overridden -(void)perform method. This way is more convenient.
[(PlayerViewController *)segue.destinationViewController setView:[PlayerView sharedPlayerView]];
PHAsset *phAsset = (PHAsset *)AppDelegate.assetsFetchResults[segue.identifier.integerValue];
[AppDelegate.cacheManager requestAVAssetForVideo:phAsset options:AppDelegate.videoOptions resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
[[PlayerView sharedPlayerView] addSubview:[PlayerControls sharedPlayerControls]];
[[PlayerControls sharedPlayerControls] setDelegate:(PlayerViewController *)segue.destinationViewController];
[[PlayerView sharedPlayerView] addSubview:[AppDelegate playerControlsLabel]];
[(PlayerViewController *)segue.destinationViewController setupPlaybackForAsset:asset completion:^{
[((AssetsCollectionViewController *)sender).navigationController presentViewController:(PlayerViewController *)segue.destinationViewController animated:TRUE completion:^{
}];
}];
}];
}
Also, add this line anywhere in the source view controller implementation file to perform the segue:
[self prepareForSegue:self.segue sender:self];
The call to the prepareForSegue method can be made inside an IBAction handler and anywhere else.
Note that the code that presents the destination view controller references a view controller that is not set up in a storyboard; the project from which this code was taken does not use storyboards for anything. BUT THAT DOESN'T MATTER because the segue code will be the same.
Also note that you do not have to modify the destination view controller in any way, shape or form. To programmatically create an unwind segue (in other words, build on the one-way segue shown here):
#implementation RootNavigationController
- (UIStoryboardSegue*)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier {
return [toViewController segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier];
}
#end
Now, that's what I've done in my own app; here's what someone else has done to create a segue without using the storyboard (vs. not having a storyboard at all):
- (void)presentSignupViewController {
// Storyboard ID
UIStoryboard *modalStoryboard = [UIStoryboard storyboardWithName:#"MyStoryboard" bundle:nil];
UINavigationController *navController = [modalStoryboard instantiateViewControllerWithIdentifier:#"MySignupViewController"];
MySignupViewController *controller = [navController viewControllers][0];
// Configure your custom view controller, e.g. setting delegate
controller.delegate = self;
// Show VC
navController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
BlurryModalSegue *segue = [[BlurryModalSegue alloc] initWithIdentifier:#"SignupScene" source:self destination:navController];
[segue perform];
}
The difference is only in the use of perform and prepareForSegue: when using no storyboard at all, you have to call your transition method of choice (push... or present...) in the performForSegue method; however, the transition method is called for you by the perform method otherwise.
<iframe width="853" height="480" src="https://www.youtube.com/embed/y8Fu2PEO2zo?rel=0&showinfo=0" frameborder="0" allowfullscreen></iframe>

Segue to a UINavigation Controller programmatically without storyboards

I have code that uses Storyboards for seques, like so:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowDiagnosis"])
{
[segue.destinationViewController setHappiness:self.diagnosis];
}
...
But I want to do it programmatically. I have myViewController class and when I click on a button I want to animate and push to myUINavigationController.
How is this done programmatically?
First things first, a segue cannot be created programmatically. It is created by the storyboard runtime when it is time to perform. However you may trigger a segue, which is already defined in the interface builder, by calling performSegueWithIdentifier:.
Other than this, you can provide transitions between view controllers without segue objects, for sure. In the corresponding action method, create your view controller instance, either by allocating programmatically or instantiating from storyboard with its identifier. Then, push it to your navigation controller.
- (void)buttonClicked:(UIButton *)sender
{
MyViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"my-vc-identifier"];
// OR MyViewController *vc = [[MyViewController alloc] init];
// any setup code for *vc
[self.navigationController pushViewController:vc animated:YES];
}
First of all segue can be used only with if you have a UINavigationController that will handle the navigation (push, pop, etc).
So if you have a UINavigationController and you want to push another UIViewController on the stack without using segue then you can use pushViewController:animated: method which also has a reverse popViewControllerAnimated:. Also UINavigationController provides other methods for adding/removing UIVIewControllers, for more info check UINavigationController class reference.

Resources