ios 如何“取消” UIStoryBoardSegue
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7819796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to "cancel" a UIStoryBoardSegue
提问by Fabio B.
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 cannot! (It depends on a couple of things)
我的表格视图单元格代表可以在向下钻取的“详细信息”视图中查看的产品……或者不能!(这取决于几件事)
Now my App considers all products "unlocked":
现在我的应用程序认为所有产品“已解锁”:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
ListaProdottiController *prodottiViewController = [segue destinationViewController];
prodottiViewController.blocco = [self.fetchedResultsController objectAtIndexPath:selectedRowIndex];
}
How can I cancel the row selection => drilldown, at this point?
此时如何取消行选择 => 向下钻取?
回答by Joshcodes
If you are targeting iOS 6 or greater, then my knowledge of the cleanest way to do this is the following:
如果您的目标是 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;
}
Where there is a method
哪里有方法
-(BOOL) meetsRequiredConditions;
Defined on your Blocco class returns YES if the "couple of things" which permit a drill-down are valid.
如果允许向下钻取的“几件事情”有效,则在您的 Blocco 类上定义的返回 YES。
回答by igbopie
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).
从情节提要中,我从视图控制器的状态栏中关联(控制+单击)一个 segue。给 segue 一个 ID(例如: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 hereand here
这样你就可以控制你的转场是否被执行。尝试从这里和这里帮助我的教程
Hope this helps.
希望这可以帮助。
回答by zirinisp
I am using an much easier and tidy approach.
我正在使用一种更简单、更整洁的方法。
Storyboard
故事板
- Create two identical cell with different identifiers. Eg: "cellWithSegue" and "cellWithoutSegue".
- Connect the first cell ("cellWithSegue") with the segue you want to display.
- Do not connect the second cell with any segue.
- 创建两个具有不同标识符的相同单元格。例如:“cellWithSegue”和“cellWithoutSegue”。
- 将第一个单元格 ("cellWithSegue") 与要显示的转场连接起来。
- 不要用任何 segue 连接第二个单元格。
Table View
表格视图
- On cellForRowAtIndexPath, implement a logic to determine if the cell should be linked a segue or not.
- For cells that should be linked with the segue use the "cellWithSegue" identifier, for the rest the "cellWithoutSegue".
- 在 cellForRowAtIndexPath 上,实现一个逻辑来确定单元格是否应该被链接到 segue。
- 对于应该与 segue 链接的单元格,使用“cellWithSegue”标识符,其余的使用“cellWithoutSegue”标识符。
This way looks a lot easier to implement and also does not alter the way segues are supposed to work.
这种方式看起来更容易实现,并且也不会改变 segue 应该工作的方式。
回答by SomaMan
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!
我在这里可能是错的,但是在为此苦苦挣扎之后,我只是在我不希望触发序列的单元格上禁用了单元格的用户交互(在 cellForRowAtIndexPath: 中)。似乎工作得很好,而且只有 1 行代码!
cell.userInteractionEnabled = NO;
回答by Johnson Mathew
The easiest solution is to create manual segue in story board and use that as seen below.
最简单的解决方案是在故事板中创建手动转场并使用它,如下所示。
[self performSegueWithIdentifier:@"loginSuccessSegue" sender:self];
Or
或者
@Fabio: I was trying to get a solution for same kind of use-cases and I almost found a solution.
@Fabio:我试图为相同类型的用例找到解决方案,我几乎找到了解决方案。
Use-cases 1. Stop segue transition conditionally 2. Change destination viewController conditionally
用例 1. 有条件地停止转场转换 2. 有条件地更改目标 viewController
Solution:
解决方案:
Use "Custom" segue. Follow below steps to create Custom segue 1. Create a subclass of UIStoryboardSegue "MyCustomSegue.h"
使用“自定义”转场。按照以下步骤创建自定义 segue 1. 创建 UIStoryboardSegue "MyCustomSegue.h" 的子类
@interface MyCustomSegue : UIStoryboardSegue
@end
"MyCustomSegue.m"
“MyCustomSegue.m”
Override initWithIdentifier for implementing use-case 1 and 2 If you return nil, segue will be cancelled/no action will be taken You instantiate your ViewController and set that as a destination. You can set destination as your old xib file also.. that code is commented, but I ensured that will work.
覆盖 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];
}
- You must override "perform".
- 您必须覆盖“执行”。
You can implement use-case 1 here also..
您也可以在这里实现用例 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];
}
Hope this helps. Plz write if you are not clear.
希望这可以帮助。如果你不清楚,请写。
回答by JK Laiho
A nice and lightweight way of doing this is inside the UITableViewDelegate method tableView:willSelectRowAtIndexPath:
—where applicable. YMMV.
tableView:willSelectRowAtIndexPath:
在适用的情况下,在 UITableViewDelegate 方法中是一种很好且轻量级的方法。天啊。
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.
这是我的做法(iOS 5,ARC)。我在视图控制器中使用了一个 BOOL 实例变量,在viewDidLoad
. 表单元格在 Interface Builder 中设置为转接的目标视图控制器依赖于从服务器加载的一些数据,因此我不希望在获得数据之前进行转接。
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.
忽略那里的 sharedClient 之类的细节,这就是我如何用成功块调用我的 AFHTTPClient 子类,在现实生活中我也会有一个失败块和其他东西。
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.
返回nil
的tableView:willSelectRowAtIndexPath:
原因敲击表格单元格什么都不做。只有在我从我的 AFHTTPClient 实例(通过 successBlock)得知 segued-to 视图控制器需要的数据准备好并等待之后,我才更改实例变量,以后的点击将正常工作。在现实生活中的代码中,您需要一些用户可见的通知或视觉上明显的指示标志,表明目前还不可能进行转场。
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.
因此,在许多情况下,无论您需要确定从表格单元格转场是否正常所需的任何逻辑,都可以以这种方式进行。
回答by valexa
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:
Apple 的模板为 iPad popOver 执行此操作的方式是使用手动转场,而不是在触摸时触发的自动转场,手动转场需要使用 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.
要创建手动转场而不是从您想到的元素按 ctrl-drag 从视图的控制器图标中按住 ctrl-drag,请为转场设置一个标识符,然后在 IB 中完成。
回答by Dorine M
Here another solution I just found.
这是我刚刚找到的另一个解决方案。
In your Mainstoryboard TableView, as you use automatic segue from your cell (identifier=Cell) to the destination view, you can also add another cell with another identifier (identifier=CellWithoutSegue). So when creating new cell in cellForRowAtIndexPath, just reuse the cell identifier you want (with or without segue).
在 Mainstoryboard TableView 中,当您使用从单元格 (identifier=Cell) 到目标视图的自动转场时,您还可以添加具有另一个标识符 (identifier=CellWithoutSegue) 的另一个单元格。因此,在 cellForRowAtIndexPath 中创建新单元格时,只需重用所需的单元格标识符(带或不带 segue)。
Hope it helps!
希望能帮助到你!
(Tell me if you want some code source examples).
(如果您想要一些代码源示例,请告诉我)。
Regards,
问候,
回答by Hank Brekke
In your - (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender;
method, you could add some code such as:
在您的- (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];
}
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).
这将阻止视图打开,但是我还没有检查,但它似乎已经调用了您的目标视图控制器初始化函数(同样,我还没有检查 Xcode,所以我不完全确定)。