如何检查视图控制器是否可以执行segue

时间:2012-03-08 23:06:03

标签: objective-c ios ios5 uistoryboardsegue

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

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

有些事情:

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

可能的?

8 个答案:

答案 0 :(得分:24)

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

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

希望这有帮助。

答案 1 :(得分:14)

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

答案 2 :(得分:11)

此帖已针对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: ...)

答案 3 :(得分:6)

如文件中所述:

  

应用通常不需要直接触发segue。   而是在Interface Builder中配置对象   视图控制器,例如嵌入在其视图层次结构中的控件,   触发segue。但是,您可以调用此方法来触发a   以编程方式进行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 documentation开始,我无法找到任何类似的内容
  3. 至于现在,我猜你最好的选择是继续使用@try @catch @finally

答案 4 :(得分:4)

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

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

希望这有帮助。

答案 5 :(得分:2)

Reference 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
    }
}

答案 6 :(得分:1)

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

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

library(shiny)
ui <- fluidPage(

  mainPanel(fluidRow(textOutput("a")),
            fluidRow(textOutput("b")))
)
server <- function(input, output) {

  m <- reactive({1:5})

  for (i in 1:length(m)){
      assign(paste0("h",i), "u")
  }

  output$a <- renderPrint({

    list(h1,h2)
  })

  output$b <- renderPrint({

   list(h1,h2)
  })
}
shinyApp(ui = ui, server = server)

答案 7 :(得分:-1)

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

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