如何“取消”UIStoryBoardSegue

时间:2011-10-19 10:20:36

标签: iphone ios uitableview ios5 storyboard

有没有人知道如何有条件地“停止”segue过渡:

我的表格视图单元格代表可以在深入“详细信息”视图中查看的产品......或者不能! (这取决于几件事情)

现在我的应用程序认为所有产品都“已解锁”:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
    ListaProdottiController *prodottiViewController = [segue destinationViewController];
    prodottiViewController.blocco = [self.fetchedResultsController objectAtIndexPath:selectedRowIndex];
}

如何取消行选择=>钻研,此时?

9 个答案:

答案 0 :(得分:79)

如果您的目标是iOS 6或更高版本,那么我对最干净方法的了解如下:

-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    if([identifier isEqualToString:@"show"])
    {
        NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
        Blocco *blocco = [self.fetchedResultsController objectAtIndexPath:selectedRowIndex];
        return [blocco meetRequiredConditions];
    }
    return YES;
}

哪里有方法

-(BOOL) meetsRequiredConditions;

如果允许向下钻取的“几件事”有效,则在Blocco类中定义返回YES。

答案 1 :(得分:32)

我不知道这是否是正确的方法,但我发现了一种解决方法。

从故事板中我将视图控制器中的状态栏关联(控制+单击)一个segue。给segue一个ID(例如:switchSegue)。

现在,通过代码中的操作(在我的代码中,我使用了一个按钮),我调用:

 [self performSegueWithIdentifier:@"switchSegue" sender:sender];

这样你可以控制你的segue是否被执行。 尝试从herehere

帮助我的教程

希望这有帮助。

答案 2 :(得分:18)

我正在使用一种更简单,更整洁的方法。

<强>故事板

  1. 创建两个具有不同标识符的相同单元格。例如:“cellWithSegue”和“cellWithoutSegue”。
  2. 将第一个单元格(“cellWithSegue”)与您要显示的segue相连接。
  3. 请勿将第二个单元格与任何segue连接。
  4. 表格视图

    1. 在cellForRowAtIndexPath上,实现一个逻辑来确定该单元格是否应该与segue链接。
    2. 对于应与segue链接的单元格,请使用“cellWithSegue”标识符,其余为“cellWithoutSegue”。
    3. 这种方式看起来更容易实现,也不会改变segues的工作方式。

答案 3 :(得分:14)

我可能在这里错了,但是在努力解决这个问题之后,我只是禁用了单元格上的用户交互,我不希望触发seque(在cellForRowAtIndexPath :)中。似乎工作得很完美,而且它只有一行代码!

cell.userInteractionEnabled = NO;

答案 4 :(得分:11)

最简单的解决方案是在故事板中创建手动segue并使用如下所示。

[self performSegueWithIdentifier:@"loginSuccessSegue" sender:self];


@Fabio:我试图找到同样用例的解决方案,我几乎找到了解决方案。

用例 1.有条件地停止segue过渡 2.有条件地更改目标viewController

解决方案:

使用“自定义”segue。 按照以下步骤创建自定义segue 1.创建UIStoryboardSegue的子类 “MyCustomSegue.h”

@interface MyCustomSegue : UIStoryboardSegue
@end

“MyCustomSegue.m”

覆盖initWithIdentifier以实现用例1和2 如果您返回nil,则segue将被取消/不会采取任何行动 您实例化ViewController并将其设置为目标。 您可以将目标设置为旧的xib文件..该代码已被注释,但我确保它可以正常工作。

@implementation MyCustomSegue
- (id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination{

    UIStoryboard *storyBoard= [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];

    UIViewController *viewController = [storyBoard instantiateViewControllerWithIdentifier:@"testIdentifier"];

    // MyViewController* viewController= [[MyViewController alloc]initWithNibName:@"MyViewController" bundle:nil];
    return [super initWithIdentifier:identifier source:source destination:viewController];
}
  1. 您必须覆盖“执行”。
  2. 您也可以在这里实现用例1.

    - (void)perform {
        // if either source or destination is nil, stop
        if (nil == self.sourceViewController || nil == self.destinationViewController) return;
        // return; //No Action. Segue will be cancelled
        UINavigationController *ctrl = [self.sourceViewController navigationController];
        [ctrl
         pushViewController:self.destinationViewController
         animated:YES];
    }
    

    希望这会有所帮助。如果你不清楚的话,请写下来。

答案 5 :(得分:4)

在UITableViewDelegate方法tableView:willSelectRowAtIndexPath:中有一个很好且轻量级的方法 - 在适用的情况下。 YMMV。

以下是我的表现(iOS 5,ARC)。我在视图控制器中使用BOOL实例变量,最初在viewDidLoad中设置为False。在Interface Builder中将表格单元设置为segue的目标视图控制器依赖于从服务器加载的一些数据,因此我不希望在我获得数据之前发生segue。

简化,这就是它的样子:

@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;
}

忽略那里的sharedClient位这样的细节,这就是我用成功块调用我的AFHTTPClient子类的方式,在现实生活中我还有一个失败块和其他东西。

nil中返回tableView:willSelectRowAtIndexPath:会导致点击表格单元格无法执行任何操作。只有在我从我的AFHTTPClient实例(通过successBlock)获得了segued-to view控制器所需的数据准备就绪并等待之后,我才更改实例变量,未来的taps将正常工作。在现实生活中的代码中,您将需要一些用户可见的通知或视觉上明显的告示标记,即无法进行隔离。

因此,在许多情况下,您需要确定从表格单元格中划分是否正常的逻辑是否可以这样做。

答案 6 :(得分:2)

Apple的模板用于iPad popOver的方式是使用手动segue,而不是触摸时触发的自动segue,需要使用performSegueWithIdentifier触发手动:

要创建手动segue,而不是从您想到的元素中按住Ctrl键拖动,请从视图的控制器图标中按住Ctrl键拖动,设置segue的标识符,然后在IB中完成。

manual segues

答案 7 :(得分:0)

这是我刚发现的另一种解决方案。

在Mainstoryboard TableView中,当您使用从单元格(标识符=单元格)到目标视图的自动segue时,您还可以添加另一个具有另一个标识符的单元格(标识符= CellWithoutSegue)。因此,当在cellForRowAtIndexPath中创建新单元格时,只需重用所需的单元格标识符(带或不带segue)。

希望它有所帮助!

(如果你想要一些代码源示例,请告诉我。)

此致

答案 8 :(得分:-1)

- (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender;方法中,您可以添加一些代码,例如:

if ([[segue identifier] isEqualToString:@"DemoSegue"] && !self.canOpenDemo) {
    id *nc = [segue destinationViewController]; // UIViewController, UINavigationController, etc. (keeping "id" will return warning)
    [nc dismissModalViewControllerAnimated:NO];
}

这会阻止视图打开,但是我没有检查过,但似乎它已经调用了你的目标视图控制器初始化函数(再次,我没有检查过Xcode,所以我不完全肯定)。