How to check from which segue does view appear? - iphone

I have view and a lot of segues from different other views to it, is there any property to check which segue does call this view?

I am not sure tht you can check it by just segue name.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"view1"])
{
[segue.destinationViewController setVariable:variable];
}
}
Create this variable in destinationViewController.
Then check value of "variable".

You make use of the the following function in your viewcontroller,In which making use of the segue identifier you are able to identify which view has called the upcoming view.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"view1"])
{
NSLog(#" called by view1");
[segue.destinationViewController setVariable:variable];
}
}

Create a #property in your destination ViewController
Assign segue identificator to it in -(void)prepareForSegue method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.destinationViewController respondsToSelector:#selector(setMyIdentifier)]) {
[segue.destinationViewController setMyIdentifier:segue.identifier];
}
}
Handle self.myIdentifier property in -viewDidLoad of your destination ViewController

Related

Not able to pass value from one view controller to another on storyboard

I have a problem I am calling WSLogin class from my Loginviewcontroller. and it successfully return my sessionId of User. then I am storing this sessionId into string and sending this value to Searchviewcontroller but not successfully submit value to Searchviewcontroller.
when I succesfully login then I move to Searchviewcontroller through tab-bar controller. I generate NSLog in searchviewcontroller to check the value of session when I click on searchtabbar after successfully login then on NSLog session id = null return to me kindly tell me how I can fix this problem?
This is the code
// LoginViewController.m file
-(IBAction)Login:(id)sender
{
wsobject = [[WSLogin alloc] init];
sessId = wsobject.sessionId;
NSLog(#"sessionidd = %#",sessId);
// it successfully return session id
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SearchViewController *afc = (SearchViewController *) segue.destinationViewController;
afc.sessionId = sessId;
// i have create sessionId property in SearchViewController
}
// SearhViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"sessionId = %#",sessionId);
//printing sessionId value but getting Null here when click on Searhtabbar
}
I'm asuming that you've already perpare segues for the same and in identity inspector gave it a name, say "goToNextView". Now put the following code where you're jumping to next view controller
-(IBAction)methodName:(id)sender
{
[self performSegueWithIdentifier:#"goToNextView" sender:self];
}
Then in your code modify prepare for segue delegate method like this
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"goToNextView"]) {
DestinatonViewController *controller = segue.destinationViewController
// set the properties value you want for destination View Controller
controller.propertyName = yourValue;
Hope this will help..

prepareForSegue not called

I'm using the template master detail application. I have added a modal segue from SplitViewController and given it the identifier "DisplayLoginView".
I call the following from my detailViewController:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
[self.splitViewController performSegueWithIdentifier:#"DisplayLoginView" sender:self.splitViewController];
}
I also have the prepareForSegue method defined in detailViewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"Source Controller = %#", [segue sourceViewController]);
NSLog(#"Destination Controller = %#", [segue destinationViewController]);
NSLog(#"Segue Identifier = %#", [segue identifier]);
if ([segue.identifier isEqualToString:#"DisplayLoginView"])
{
PrometheusLoginViewController *loginViewController = (PrometheusLoginViewController *)segue.destinationViewController;
loginViewController.delegate = self;
}
}
Any idea on why it's not called?
You're asking the splitViewController to perform the segue, but you're defining prepareForSegue in the detailViewController. They need to be on the same object for prepareForSegue to be triggered.

Push detail controller from search display controller's table view

I implemented a search option in my app but when I search something, I can't push a detail controller from the search display controller's table view.
Is there a way to do that?
Thank you so much!
We'll assume you have a UISearchBarDelegate method in a UIViewController called SearchViewController. To push (DetailViewController*) dvc, implement these methods in SearchViewController:
#pragma mark - Search bar delegate
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if (searchTextMatchedSomeTarget) {
textForDetailView = searchText;
[self performSegueWithIdentifier:seguePushDetailView sender:self];
}
}
#pragma mark - View lifecycle
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:seguePushDetailView]) {
dvc = (DetailViewController *)[segue destinationViewController];
dvc.delegate = (id)self;
dvc.searchText = textForDetailView;
}
}
#pragma mark - Detail view controller protocol delegate
- (void)DetailViewControllerDidFinish:(DetailViewController *)controller
{
NSString *somethingBackFromDetailView = controller.backToSearchView;
}
UIDetailViewController declares a protocol with the "did finish" method and properties of whatever type you like, both to receive data from SearchViewController and to send back any data after any detail processing. The segue is added in Xcode IB by control dragging from UISearchViewController to UIDetailViewController. NB: the segue source and destination are the view controllers themselves. That way they can be invoked programmatically as opposed to automatic invocation on a tap event.

If-statement in prepareForeSegue in iOS 5

I have a problem with the Storyboard in xCode 4.2. Is it posible to check, if a boolean is true to load the next view or if it is false to do not load the new view an stay in the actual view.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"toCategory"] && ([[codeField text] isEqualToString:#"1234"]))
{
QuestInfoController *qicontroller = [segue destinationViewController];
}
else
{
[super prepareForSegue:segue sender:self];
return;
}
}
Yes, but you don't do it quite like this. You'd use a custom method or check for your boolean value - then you'd use performSegueWithIdentifier: to force the transition based on the outcome.
I wrote another post about it here. It demonstrates how to wire a few buttons on a page to push the next view. Note that in the buttonPressed: method would be where you do your check.

UIStoryboardPopoverSegue opening multiple windows on button touch

I'm using a UIStoryboardPopoverSegue to present a popover for an iOS 5 iPad app. The Segue works great, but it seems like the toolbar that contains the button is a passthrough view for the popover controller so if you keep pressing the button, more popovers appear. As I'm not creating and keeping track of the UIPopoverController myself (as the Storyboard is doing it) I can't dismiss it when the button is touched again. Has anyone else run into this? I have a bug open with Apple but they haven't responded.
EDIT: I've solved this using the answer below. Here is the code I ended up using. currentPopover is a __weak ivar in my view controller class, so when the controller is done it will drop to nil automatically.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue isKindOfClass:[UIStoryboardPopoverSegue class]]){
// Dismiss current popover, set new popover
[currentPopover dismissPopoverAnimated:YES];
currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
}
}
There are some visual issues with the your solution Cory.
Two options that can be considered - simply remove or change the action of the button that presents the popover.
Option 1, hold a pointer to the button's action, and after the popover is presented, set the action to nil. Upon dismissal of the popover reset to the original action.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
action = [sender action];
[sender setAction:nil];
self.currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
self.currentPopover.delegate = self;
}
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
[self.navigationItem.rightBarButtonItem setAction:action];
return YES;
}
This way the popover can only appear once, and will be dismissed as expected.
A second option would be to change the function of the button so that when the popover is visible, tapping the button will cause the popover to be dismissed.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
action = [sender action];
target = [sender target];
[sender setTarget:self];
[sender setAction:#selector(dismiss:)];
self.currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
self.currentPopover.delegate = self;
}
-(void)dismiss:(id)sender
{
[self.navigationItem.rightBarButtonItem setAction:action];
[self.navigationItem.rightBarButtonItem setTarget:target];
////or
// [sender setAction:action];
// [sender setTarget:target];
[self.currentPopover dismissPopoverAnimated:YES];
}
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
[self.navigationItem.rightBarButtonItem setAction:action];
[self.navigationItem.rightBarButtonItem setTarget:target];
return YES;
}
Simply connect a UIBarButtonItem via IBAction. Use the itendifier set in interface builder:
-(IBAction)barButtonItemPressed:(id)sender {
if (currentPopoverController && currentPopoverController.popoverVisible) {
[currentPopoverController dismissPopoverAnimated:YES];
currentPopoverController = nil;
} else {
[self performSegueWithIdentifier:#"aSegueIdentifier" sender:sender];
}
}
Get a reference of the new UIPopoverCOntroller from the seque:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"aSegueIdentifier"])
currentPopoverController = [(UIStoryboardPopoverSegue *)segue popoverController];
}
currentPopoverController is an instance variable, defined in header file:
UIPopoverController *currentPopoverController;
Important: The anchor property of the seque must be set to the corresponding UIBarButtonItem!
You have to store a reference to the popoverController property passed as part of the UIStoryboardPopoverSegue class in the prepareForSegue class method.
To access it, over-ride the method in the calling view controller like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// The Storyboard Segue is named popover in this case:
if ([segue.identifier compare:#"popover"] == NSOrderedSame) {
// segue.popoverController is only present in popover segue's
// self.seguePopoverController is a UIPopoverController * property.
self.seguePopoverController = segue.popoverController;
}
}
Then you can dismiss it in the usual way.
This solution could also have visual issues, but it doesn't for my simple case. In my case, the popover was just displaying some help. I put together the following (with ARC) that will dismiss the popover viewcontrollers when the button bar button is pressed a second time (both the original and the newly created one).
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if( [segue isKindOfClass:[UIStoryboardPopoverSegue class]] )
{
UIStoryboardPopoverSegue *popoverSegue = (id)segue;
UIPopoverController *popoverController = popoverSegue.popoverController;
if( m_popoverController.popoverVisible )
{
[m_popoverController dismissPopoverAnimated:NO];
dispatch_async( dispatch_get_main_queue(), ^{
[popoverController dismissPopoverAnimated:YES];
});
m_popoverController = nil;
}
else
m_popoverController = popoverController;
}
}
I also added some cleanup in dealloc
- (void)dealloc
{
if( m_popoverController.popoverVisible )
[m_popoverController dismissPopoverAnimated:YES];
}
It does require a member variable in your class
UIPopoverController *m_popoverController;
I prefer to use a static weak variable, which keeps everything together in one place:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showSomething"]) {
static __weak UIPopoverController* currentPopover = nil;
[currentPopover dismissPopoverAnimated:NO];
currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
// ...
}
}
There's no reason to add a separate extra variable (when are you going to have multiple instances of the view controller?), and this way you can add an extra variable for each if() block.
June 14 2013
Thanks for edit in question. Rather than dismissing and recreating the view controller - to avoid performance and battery concerns and prevent Flash when dismissing and recreating view controller - how about preventing the second instance of popover from popping?
//place in view controller (tested iOS6+, iPad, iPhone)
__weak UIPopoverController *popover;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue isKindOfClass:[UIStoryboardPopoverSegue class]]
&& [segue.identifier isEqualToString:#"mySegue"]) //remember to change "mySegue"
popover = [(UIStoryboardPopoverSegue *)segue popoverController];
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if ([identifier isEqualToString:#"mySegue"]) //remember to change "mySegue"
return !popover;
else
return YES;
}
added checks to: http://stackoverflow.com/a/10238581/1705353
This is also good.
#interface ViewController : UIViewController <UIPopoverControllerDelegate> {
UIPopoverController * seguePopoverController;
}
#property (strong) UIPopoverController * seguePopoverController;
#end
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (self.seguePopoverController) {
[self.seguePopoverController dismissPopoverAnimated:NO];
self.seguePopoverController = nil;
}
// The Storyboard Segue is named popover in this case:
if ([[segue identifier] isEqualToString:#"popover"]) {
UIStoryboardPopoverSegue* popSegue = (UIStoryboardPopoverSegue*)segue;
UIPopoverController *thePopoverController = [popSegue popoverController];
thePopoverController.delegate = self;
self.seguePopoverController = thePopoverController;
}
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
self.seguePopoverController = nil;
}