36

这可能是一个非常简单的问题,但在搜索它时没有产生任何结果,所以它在这里......

我正在尝试找出一种方法来检查某个视图控制器是否可以在调用该performSegueWithIdentifier:方法之前执行带有标识符 XYZ 的 segue。

类似于以下内容:

if ([self canPerformSegueWithIdentifier:@"SegueID"])
    [self performSegueWithIdentifier:@"SegueID"];

可能的?

4

9 回答 9

24

为了检查 segue 是否存在,我只是用一个 try-and-catch 块包围了调用。请看下面的代码示例:

@try {
    [self performSegueWithIdentifier:[dictionary valueForKey:@"segue"] sender:self];
}
@catch (NSException *exception) {
    NSLog(@"Segue not found: %@", exception);
}

希望这可以帮助。

于 2013-02-15T00:12:03.480 回答
15
- (BOOL)canPerformSegueWithIdentifier:(NSString *)identifier
{
    NSArray *segueTemplates = [self valueForKey:@"storyboardSegueTemplates"];
    NSArray *filteredArray = [segueTemplates filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"identifier = %@", identifier]];
    return filteredArray.count>0;
}
于 2015-06-11T06:04:59.187 回答
14

这篇文章已针对 Swift 4 进行了更新。


这是一个更正确的Swift 检查是否存在 segue 的方法:

extension UIViewController {
func canPerformSegue(withIdentifier id: String) -> Bool {
        guard let segues = self.value(forKey: "storyboardSegueTemplates") as? [NSObject] else { return false }
        return segues.first { $0.value(forKey: "identifier") as? String == id } != nil
    }

    /// Performs segue with passed identifier, if self can perform it.
    func performSegueIfPossible(id: String?, sender: AnyObject? = nil) {
        guard let id = id, canPerformSegue(withIdentifier: id) else { return }
        self.performSegue(withIdentifier: id, sender: sender)
    }
}

// 1
if canPerformSegue("test") {
    performSegueIfPossible(id: "test") // or with sender: , sender: ...)
}

// 2
performSegueIfPossible(id: "test") // or with sender: , sender: ...)
于 2015-10-05T13:47:06.920 回答
6

如文档中所述:

应用程序通常不需要直接触发 segue。相反,您在 Interface Builder 中配置与视图控制器关联的对象,例如嵌入在其视图层次结构中的控件,以触发 segue。但是,您可以调用此方法以编程方式触发 segue,可能是为了响应无法在情节提要资源文件中指定的某些操作。例如,您可以从用于处理抖动或加速度计事件的自定义操作处理程序中调用它。

接收此消息的视图控制器必须已从情节提要中加载。如果视图控制器没有关联的故事板,可能是因为您自己分配和初始化了它,此方法将引发异常。

话虽如此,当您触发 时segue,通常是因为假定UIViewController将能够使用特定segue's标识符对其进行响应。我也同意 Dan F,您应该尽量避免可能引发异常的情况。作为你不能做这样的事情的原因:

if ([self canPerformSegueWithIdentifier:@"SegueID"])
    [self performSegueWithIdentifier:@"SegueID"];

我猜想:

  1. respondsToSelector:仅检查您是否能够在运行时处理该消息。在这种情况下你可以,因为类UIViewController能够响应performSegueWithIdentifier:sender:. 要实际检查一个方法是否能够处理带有某些参数的消息,我想这是不可能的,因为为了确定它是否可能,它必须实际运行它,并且在这样做的时候NSInvalidArgumentException会上升。
  2. 要实际创建您建议的内容,接收UIViewController与之关联的 segue id 列表会很有帮助。从UIViewController 文档中,我找不到任何类似的东西

至于现在,我猜你最好的选择是继续使用@try @catch @finally.

于 2012-06-28T09:26:08.497 回答
4

您可以覆盖 -(BOOL)shouldPerformSegueWithIdentifier:sender: 方法并在那里执行您的逻辑。

- (BOOL) shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
    if ([identifier isEqualToString:@"someSegue"]) {
        if (!canIPerformSegue) {
            return NO;
        }
    }
    return YES;    
}

希望这可以帮助。

于 2015-03-23T19:29:36.840 回答
2

参考 CanPerformSegue.swift

import UIKit

extension UIViewController{
    func canPerformSegue(identifier: String) -> Bool {
        guard let identifiers = value(forKey: "storyboardSegueTemplates") as? [NSObject] else {
            return false
        }
        let canPerform = identifiers.contains { (object) -> Bool in
            if let id = object.value(forKey: "_identifier") as? String {
                return id == identifier
            }else{
                return false
            }
        }
        return canPerform
    }
}
于 2018-10-29T16:30:20.100 回答
1

Evgeny Mikhaylov 的答案的 Swift 版本,对我有用:

我为两个视图重用了一个控制器。这有助于我重用代码。

if(canPerformSegueWithIdentifier("segueFoo")) {
  self.performSegueWithIdentifier("segueFoo", sender: nil)
}
else {
  self.performSegueWithIdentifier("segueBar", sender: nil)
}


func canPerformSegueWithIdentifier(identifier: NSString) -> Bool {
    let templates:NSArray = self.valueForKey("storyboardSegueTemplates") as! NSArray
    let predicate:NSPredicate = NSPredicate(format: "identifier=%@", identifier)

    let filteredtemplates = templates.filteredArrayUsingPredicate(predicate)
    return (filteredtemplates.count>0)
}
于 2015-09-03T13:46:19.613 回答
0

这将很有用,在调用 performSegue 之前,检查基本 UIViewController 上的本机故事板属性(例如屏幕来自 StoryBoard 或手动实例)

extension UIViewController {

func performSegueWithValidate(withIdentifier identifier: String, sender: Any?) {
    if storyboard != nil {
        performSegue(withIdentifier: identifier, sender: sender)
    }
}

} 在这里输入图片描述

于 2021-08-13T08:17:41.183 回答
-1

没有办法检查使用标准函数,您可以做的是子类UIStoryboardSegue化并将信息存储在source视图控制器(传递给构造函数)中。在界面生成器中,选择“自定义”作为 segue 类型,输入 segue 的类名,然后将为每个实例化的 segue 调用构造函数,如果存储的数据存在,则可以查询它。

您还必须覆盖perform要调用的方法[source presentModalViewController:destination animated:YES][source pushViewController:destination animated:YES]取决于您想要的转换类型。

于 2012-06-28T09:46:26.123 回答