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

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

大致如下:

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

可能的?

有帮助吗?

解决方案

如文档中所述:

应用程序通常不需要直接触发 segue。相反,您将与视图控制器关联的接口构建器中配置一个对象,例如嵌入在视图层次结构中的控件,以触发SEGUE。但是,您可以调用此方法以编程为触发SEGUE,也许是为了响应故事板资源文件中无法指定的某些操作。例如,您可以从用于处理摇动或加速度计的自定义操作处理程序中调用它。

接收此消息的视图控制器必须是从故事板上加载的。如果视图控制器没有关联的故事板,也许是因为您自己分配和初始化了,则此方法会引发异常。

话虽这么说,当你触发 segue, ,通常这是因为假设 UIViewController 将能够以特定的方式回应它 segue's 标识符。我也同意 Dan F 的观点,你应该尽量避免可能引发异常的情况。作为你不能做这样的事情的原因:

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

我猜测:

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

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

其他提示

检查segue是否存在,我只是用一个温度和捕获块围绕着呼叫。请参阅下面的代码示例:

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

希望这有帮助。

- (BOOL)canPerformSegueWithIdentifier:(NSString *)identifier
{
    NSArray *segueTemplates = [self valueForKey:@"storyboardSegueTemplates"];
    NSArray *filteredArray = [segueTemplates filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"identifier = %@", identifier]];
    return filteredArray.count>0;
}
.

此帖子已被更新为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: ...)
.

您可以覆盖 - (bool)ukiverformseguewith identifier:sender:方法,在那里做你的逻辑。

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

希望这有帮助。

参考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
    }
}
.

evgeny mikhaylov的答案的Swift版本,它为我工作:

i重复使用控制器两种视图。这有助于我重用代码。

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top