Swift 中的自定义 Segue

Posted

技术标签:

【中文标题】Swift 中的自定义 Segue【英文标题】:Custom Segue in Swift 【发布时间】:2014-06-12 13:12:55 【问题描述】:
@objc(SEPushNoAnimationSegue)
class SEPushNoAnimationSegue: UIStoryboardSegue 
    override func perform () 
      self.sourceViewController.navigationController.pushViewController(self.destinationViewController, animated:false)
    

在上面的代码中,我有两个问题: 1)。它有一个编译错误: “UINavigationController!”没有名为“pushViewController”的成员

但在那个类中,它确实有一个 pushViewController 方法。

2)。我必须添加注释:@objc(SEPushNoAnimationSegue), 否则,在情节提要中,它只能识别随机生成的名称,例如 _tcxxxxSEPushNoAnimationSegue。

为什么这两个问题会在这里发生?

【问题讨论】:

【参考方案1】:

问题 #1

UIStoryboardSegue 有一个恼人的缺陷:它的 sourceViewController 和destinationViewController 属性类型为AnyObject!(即使在Objective-C(Id 类型)中也是如此)而不是UIViewController,因为它应该是。

同样的缺陷会对您完美而简单的代码造成严重破坏。以下是如何重写它以修复编译错误:

@objc(SEPushNoAnimationSegue)
class SEPushNoAnimationSegue: UIStoryboardSegue 
    override func perform () 
        let src = self.sourceViewController as UIViewController
        let dst = self.destinationViewController as UIViewController
        src.navigationController.pushViewController(dst, animated:false)
    

注意:Apple 在 ios 9 中修复了这个问题。sourceViewControllerdestinationViewController 现在正确声明为 UIViewController

问题 #2

Swift 编译器使用自己的name mangling 存储它的符号,而好的 ol'Objective-C 在 Xcode 中无法识别它。使用显式 @obj() 可以解决问题。

【讨论】:

我得到了这个:Can't unwrap Optional.None 显式 @objc() - 很棒的建议 - 这就是为我做的事情 swift 命名约定的目的是避免与其他导入冲突。 只需在Storyboard中将特定Segue的模块设置为你的项目 我不敢相信仅仅在类声明前添加@objc(classname) 就可以工作... facepalm【参考方案2】:

这对我来说很好用

@objc(SEPushNoAnimationSegue) class SEPushNoAnimationSegue: UIStoryboardSegue 

override func perform() 
    let sourceViewController = self.sourceViewController as UIViewController
    let destinationViewController = self.destinationViewController as UIViewController

    sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)



【讨论】:

【参考方案3】:

更好:

import UIKit

class CustomSegue: UIStoryboardSegue 
    override func perform() 
        self.sourceViewController.presentViewController(self.destinationViewController as UIViewController, animated: false, completion: nil)
    

【讨论】:

【参考方案4】:

斯威夫特 3.0:

import UIKit

class CustomNoAnimationSegue: UIStoryboardSegue 

    override func perform() 
        if let navigation = source.navigationController 
            navigation.pushViewController(destination, animated: false)
        
    

【讨论】:

以上是关于Swift 中的自定义 Segue的主要内容,如果未能解决你的问题,请参考以下文章

从 Swift 中的自定义数据单元开始

使用自定义表格视图单元格中的故事板segue

iOS中的自定义segue

动画状态栏以及segue中的自定义转换

具有单独移动背景的自定义 segue

不使用 Storyboard segues 的自定义视图转换 (Swift)