Seguing to a View Controller that´s already been initialized - ios

I got a problem with a universal app that were initial design for the iPhone and I used a 3rd party class for a popup on the iPhone. on the iPad I want to use the Apple provided popup. My problem is my code is written so that the View Controller for the popup already is initialized in the viewDidLoad of the class containing the popup, and when seguing - a new instance of that class is allocated. Is there a way to pass it the bckMusicPlayer that´s already been allocated in prepareForSegue?
#property (nonatomic,strong) MJDetailViewController *bckMusicPlayer; //Already initialized when prepareForSegue get´s called. I want to segue to this object.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"prepare for segue");
if ([segue.identifier isEqualToString:#"Show iPad Player"]) {
if ([segue isKindOfClass:[MJDetailViewController class]]) {
}
}
}
edit: I got it working passing it the player (AVAudioPlayer) object from bckMusicPlayer
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Show iPad Player"]) {
NSLog(#"class: %#",[segue class]);
if ([segue.destinationViewController isKindOfClass:[MJDetailViewController class]]) {
NSLog(#"prepare for segue");
MJDetailViewController *destinationVC = segue.destinationViewController;
destinationVC.player = self.bckMusicPlayer.player;
}
}
}

Can't you go the other way round? Why do you have to create an instance of MJDetailViewController? Let the segue do it for you and then in prepareForSegue: you grab the destination controller and pass it the required data. Don't fight the framework.
Alternatively you could override:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
And prevent the segue in case it is targeting MJDetailViewController and manually transfer to your controller and present it.

No, you can't do that. Segues (other than unwinds) always instantiate new controllers. You either need to not instantiate it in the viewDidLoad, or move to the new controller in code rather than using a segue.

Related

Programmatically segue..works ever

I'm trying to create a manual segue, which happens only if there is a certain conidition (a successful login).
The steps I have followed are these:
1) I've created a button in source viewcontroller, and i connected the button with a drag with the destination viewcontroller.
2) I set the identifier for the segue, calling it login_ok
3) I've created a -(IBAction)buttonPressed:(id)sender
Now, I tried to make an example, to see if the work or not. I wrote:
- (IBAction)buttonPressed:(id)sender
{
BOOL test = false;
if(test == true)
{
[self performSegueWithIdentifier:#"login_ok" sender:self];
}
Theoretically, the segue should not work, because i set test=false, and i said the segue should work only if test=true.
But the segue works and makes me go to the destination viewcontroller.
Why?
If you connected the button with a drag to the destination controller, it should segue anyway.
You need to connect the segue between screens and not from the button to the screen. Then, you can control your segue from the code.
You should define your segue between controllers not from button to the controller. Defining segue between view controllers is more useful than defining segue from any component to a view controller, because when you want to use a condition for any action, you can use these two methods effectively
[self performSegueWithIdentifier:#"segueID" sender:self];
and
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
For example:
- (IBAction)buttonPressed:(id)sender
{
BOOL test = YES;
if(test == YES)
[self performSegueWithIdentifier:#"login_ok" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"login_ok"])
{
YourNextController *controller = [segue destinationViewController];
controller.welcomeText = #"Hi! Test is true congratulations";
}
}
Especially passing data from controller to another one, this way is always useful.

Passing data to destination view controller with performSegue

So I know that if there is a segue which is setup and activated through the storyboard, one can use the prepareForSegue method to pass data to the destination view controller.
I'm wondering if there is a way to do this if one uses the performSegueWithIdentifier method? It seems the prepareForSegue method is only called if the segue is activated with the storyboard, not with performSegue.
One particular problem is that I can't access the UIStoryboardSegue (it is not an argument in performSegue as it is in prepareForSegue), and therefore can't access the destination VC either.
Answer is here in StackOverflow.
How to pass prepareForSegue: an object
// When any of buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
[self performSegueWithIdentifier:#"MySegue" sender:sender];
}
// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
// Get destination view
SecondView *vc = [segue destinationViewController];
// Get button tag number (or do whatever you need to do here, based on your object
NSInteger tagIndex = [(UIButton *)sender tag];
// Pass the information to your destination view
[vc setSelectedButton:tagIndex];
}
}

IOS prepareForSegue pass a data successfully but viewdidload clear it?

In UIViewController A I performSegue to UIViewControllerB.And in the prepaerForSegue function of A, I use set function set a strong variable 's value of B. However, when the B's viewDidLoad() called, the value is nil.
Anybody help me and tell me why?
my code is:
UIViewController A:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
CXPWDViewController *cxpwdViewController=[[CXPWDViewController alloc] init];
//I can't use the segue.desinationViewController, cause it is a present modally , the desinationViewController is navigationViewController.
[cxpwdViewController setAction:#"EnterPasscode"];//here the cxpwdViewController .action is #"EnterPasscode"
}
UIViewController B:
-(void) viewDidLoad()
{
[super viewDidLoad];// here the cxpwdViewController .action is nil; Why?
}
If you are presenting an UINavigationViewController, then the rootViewController controller should be your CXPWDViewController. So that you can typeacast the same. Since you are creating an anaother viewcontroller instance you are not getting the value.Try this code.
UIViewController A:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue destinationViewController] isKindOfClass:[UINavigationViewController class]])
{
UINavigationViewController* destinationNavController =(NavigationViewController*)[segue destinationViewController];
CXPWDViewController *cxpwdViewController=(CXPWDViewController*)[destinationNavController.viewControllers firstObject];
if([cxpwdViewController isKindOfClass:[CXPWDViewController class]])
{
[cxpwdViewController setAction:#"EnterPasscode"];
}
}
}
CXPWDViewController *cxpwdViewController=[[CXPWDViewController alloc] init];
//I can't use the segue.desinationViewController
I don't know why you think you can't use the segue destination view controller. But in any case you certainly can't do what you want to do this way. You are creating a completely different CXPWDViewController - and then destroying it an instant later. You won't get far that way!

how to get identifier of current segue

I have a bug in a rendering of a view but only when the user hits the back button in a UINavigationController. I am thinking about just supressing the offending code via something like this:
if(currentSuge.identifier isEqualToString:#'pushItemSegue'){
doCode // only in this situation
}
How would I get the name of the identifier of the current segue?
This is not possible. You cannot simply get the "current Segue" at any point in the app. Because Segues Exist only at specific points in time during your Apps Life cycle. That being when your app is preparing for the transition from one view controller to another and also during the actual visual transition.
The best you can do is override -prepareForSegue: and store the UIStoryboardSegue somewhere in your ViewController as a property.
more info: https://developer.apple.com/library/ios/documentation/uikit/reference/UIStoryboardSegue_Class/Reference/Reference.html
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//Here you have name of your segue
NSLog(#"Segue name is %#", [segue identifier]);
//Use this to performe some action
if ([[segue identifier] isEqualToString:#"pushItemSegue"])
{
//your code
}
//Add this for next seque
if ([[segue identifier] isEqualToString:#"secondSegue"])
{
//someting else
}
}

iOS - Storyboard - Delegate for pop over

I'm using storyboard in my ipad application and successfully able to do transitions, use segues etc.
Currently I am showing pop over view controller on click of a button. I want to detect when the pop over dismisses.
How can I do it?
Here is what I did:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"popover"])
{
UIStoryboardPopoverSegue *pop = (UIStoryboardPopoverSegue*)segue;
pop.popoverController.delegate = self;
}
}
UIPopoverController
Now with my revelation that you're talking about a UIPopoverController, here are the steps:
Setup the UIPopoverController with an appropriate delegate (I'm assuming the "sender" view controller)
Have your "sender" conform to the UIPopoverControllerDelegate
Implement the – popoverControllerDidDismissPopover: message and have any detection logic here
Implement - prepareForSegue:sender: and use the segue's destinationController to both get a reference and set the delegate, something like below:
((MyViewController*)segue.destinationController).delegate = self;
Modal View Controller
Add a delegate to the view controller that is being presented
Name your segue if you haven't already
Have your base view controller implement - prepareForSegue:sender: (refer to the UIViewController documentation)
Assign the sending view controller as the modal view controller's delegate in prepareForSegue:sender:
Call a desired method on the delegate immediately before or after you call dismissModalViewControllerAnimated:
That is how I would approach this. I would also recommend having a formal protocol to conform your sending view controller with.
Create a segue in view controller:
#property (strong, nonatomic) UIStoryboardPopoverSegue* popSegue;
In XIB, create an identifier called "popover" for the view.
In Interface, write the following code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if( [[segue identifier] isEqualToString:#"popover"] )
{
//[[segue destinationViewController] setDelegate:self];
NSLog(#"%#",[[segue destinationViewController] viewControllers]);
self.popSegue = (UIStoryboardPopoverSegue*)segue;
.
.
.
}
Write the following code to dismiss the pop over by coding:
[self.popSegue.popoverController dismissPopoverAnimated:YES];
Since UIStoryboardPopoverSegueis deprecated in iOS 9, you can use a UIStoryboardPopoverPresentationSegue.
Then in prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)you can set the delegate like this:
Swift:
if let identifier = segue.identifier where identifier == "showPopover" {
let destVC = segue.destinationViewController as! UIViewController
destVC.popoverPresentationController?.delegate = self
}
An Objective-C code for the question is below.
if ([segue.identifier isEqualToString:#"home_login"])
{
UIViewController *dest = segue.destinationViewController;
dest.popoverPresentationController.delegate = self;
}
- (BOOL) popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
return NO;
}

Resources