首页 > 解决方案 > 混淆 Swift 中的 Segue 参数,也许是传统的编写方式?

问题描述

我正在阅读有人在这样的函数中编写 performSegue 方法:

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
    guard let annotation = mapView.selectedAnnotations.first else {return}
    selectedRestaurant = annotation as? RestaurantItem
    self.performSegue(withIdentifier: Segue.showDetail.rawValue, sender: self)
}

我的问题是,从我读过的其他书籍中,包括 Apple 的 XCode 12 手册,我会想到写这样的东西。

performSegue(withIdentifier: showDetail, sender: nil)

我无法理解添加self之前performSegue和之后的含义/意义,sender:因为它们看起来是多余的。

同样,我会showDetail简单地写为 Segue 标识符。Segue.之前和.rawValue之后是什么showDetail?我似乎找不到其他人以这种方式教人们写作。

当我在阅读 2020 年和/或 2021 年写的书时,这可能是某种传统的 Segue 写作方式吗?

谢谢...!

标签: iosswiftxcodesegue

解决方案


sender参数是任意的,并且出于与该prepare(for segue:sender:)方法的兼容性原因。

在硬编码的 segue 中,sender是 theUITableViewCell或 theUIViewController取决于连接。

performSegue(withIdentifier:sender你可以通过任何你想要的。如果您不需要sender通行证nil,但您甚至可以通过通行证annotation来摆脱临时财产。


关于标识符,处理标识符的类型安全且更复杂的方法是协议,例如

protocol SegueHandlerType {
    associatedtype SegueIdentifier : RawRepresentable
}

和一个重载performSegue(withIdentifier:sender:方法的扩展

extension SegueHandlerType where Self : UIViewController, SegueIdentifier.RawValue == String {
    
    func performSegue(withIdentifier segueIdentifier : SegueIdentifier, sender: Any?) {
        performSegue(withIdentifier: segueIdentifier.rawValue, sender:sender)
    }
    
    func segueIdentifer(for segue : UIStoryboardSegue) -> SegueIdentifier {
        guard let identifier = segue.identifier, let segueIdentifier = SegueIdentifier(rawValue: identifier) else {
            fatalError("Invalid segue identifier \(segue.identifier!)")
        }
        return segueIdentifier
    }
}

好处是标识符是在编译时检查的枚举。

然后你可以在视图控制器中采用协议并声明

enum SegueIdentifier : String {
    case pushDetail = "PushDetail"
}

...

performSegue(withIdentifier: .pushDetail, sender: annotation)

prepare(for segue可以检查

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segueIdentifer(for: segue) == .pushDetail {
       let annotation = sender as! RestaurantItem
...

推荐阅读