Does anyone know how to \"stop\" a segue transition conditionally:
My table view cells represent products which can be viewed in a drill-down \"detail\" view... or
In your - (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender; method, you could add some code such as:
if ([[segue identifier] isEqualToString:@"DemoSegue"] && !self.canOpenDemo) {
id *nc = [segue destinationViewController]; // UIViewController, UINavigationController, etc. (keeping "id" will return warning)
[nc dismissModalViewControllerAnimated:NO];
}
And this will stop the view from opening, however I have not checked, but it seems like it will have already called your destination view controllers initialize function (again, I haven't checked in Xcode, so I'm not entirely sure).
The way Apple's template does it for the iPad popOver is by using a manual segue, as opposed to a automatic segue that triggers on a touch the manual one needs to be triggered with performSegueWithIdentifier:
To create a manual segue instead of ctrl-dragging from the element you have in mind ctrl-drag from the view's controller icon, set a identifier for the segue and you are done in IB.

I am using an much easier and tidy approach.
Storyboard
Table View
This way looks a lot easier to implement and also does not alter the way segues are supposed to work.
I don't know if it is the right way to do it but I discovered a workaround.
From the storyboard I associate(control+click) a segue from the status bar in the view controller. Give the segue an ID (for example: switchSegue).
Now, from an action in your code (in my code I use a button), I call:
[self performSegueWithIdentifier:@"switchSegue" sender:sender];
That way you can control if your segue is performed or not. Try tutorials that helped me from here and here
Hope this helps.
A nice and lightweight way of doing this is inside the UITableViewDelegate method tableView:willSelectRowAtIndexPath:—where applicable. YMMV.
Here's how I'm doing it (iOS 5, ARC). I use a BOOL instance variable in my view controller, initially set to False in viewDidLoad. The destination view controller that the table cells are set to segue to in Interface Builder rely on a bit of data having gotten loaded from a server, so I don't want the segue to happen until I have the data.
Simplified, this is what it looks like:
@implementation SomeViewController {
BOOL okayToSegue;
}
...
- (void)viewDidLoad
{
[super viewDidLoad];
okayToSegue = NO;
// The success block for the data retrieval
void(^successBlock)(void) = ^{
// Other code...
okayToSegue = YES;
}
[[ServerClient sharedClient] getDataFromServerSuccess:successBlock];
}
...
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!okayToSegue) {
return nil;
}
return indexPath;
}
Ignore details like that sharedClient bit there, it's just how I'm calling out to my AFHTTPClient subclass with the success block, in real life I'd have a failure block and other things as well.
Returning nil in tableView:willSelectRowAtIndexPath: causes tapping on a table cell to do nothing. Only after I've gotten word from my AFHTTPClient instance (through successBlock) that the data the segued-to view controller needs is ready and waiting, I change the instance variable and future taps will work just fine. In real-life code, you'll want to have some user-visible notification or visually obvious tell-tale sign that segueing is not yet possible.
So whatever logic you need to determine if segueing from a table cell is OK or not is, in many cases, possible to do in this manner.
I may be wrong here, but after struggling myself with this, I just disabled the cell's user interaction on the cells where I didn't want the seque triggered (in cellForRowAtIndexPath:). Seems to work perfectly, and it's only 1 line of code!
cell.userInteractionEnabled = NO;