How to “cancel” a UIStoryBoardSegue

前端 未结 9 1796
小蘑菇
小蘑菇 2020-12-23 21:40

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

相关标签:
9条回答
  • 2020-12-23 21:48

    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).

    0 讨论(0)
  • 2020-12-23 21:49

    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.

    manual segues

    0 讨论(0)
  • 2020-12-23 21:50

    I am using an much easier and tidy approach.

    Storyboard

    1. Create two identical cell with different identifiers. Eg: "cellWithSegue" and "cellWithoutSegue".
    2. Connect the first cell ("cellWithSegue") with the segue you want to display.
    3. Do not connect the second cell with any segue.

    Table View

    1. On cellForRowAtIndexPath, implement a logic to determine if the cell should be linked a segue or not.
    2. For cells that should be linked with the segue use the "cellWithSegue" identifier, for the rest the "cellWithoutSegue".

    This way looks a lot easier to implement and also does not alter the way segues are supposed to work.

    0 讨论(0)
  • 2020-12-23 21:53

    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.

    0 讨论(0)
  • 2020-12-23 21:54

    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.

    0 讨论(0)
  • 2020-12-23 22:01

    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;
    
    0 讨论(0)
提交回复
热议问题