玩Swift ..故事板Segues

《玩转周围》是一篇实验性文章,探讨了Swift中不同的处理方式。 在一个项目中表现出色的技术在下一个项目中可能并不理想,因此,这些文章将很少讨论什么是做事的最佳方法,而更多是关于做事的更好方法。

如果您使用情节提要,您可能会看到类似以下内容:

 覆盖func prepare(用于segue:UIStoryboardSegue,发件人:任意?){ 
如果segue.identifier ==“ pushMovie” {
让电影=电影[tableView.indexPathForSelectedRow!.row]
让movieVC = segue.destination作为! MovieViewController
movieVC.movi​​e =电影
}否则,如果segue.identifier ==“ addMovie” {
让movieFormNC = segue.destination作为! UINavigationController
让movieFormVC = movieFormNC.viewControllers.first作为! MovieFormViewController
movieFormVC.delegate =自我
}
}

这段代码确实还不错。 它可能会给我们的视图控制器增加不必要的膨胀? 并且可以肯定,我们会错误地复制segue标识符。 我们必须进行一些强制施法。 但是,任何错误都会在我们看到运行时错误后立即解决。

尽管进行了合理化,但让我们看看是否可以使其变得更好……

首先,让我们看看Google是否可以帮助我们。

这使我想到了2015年的Natasha The Robot博客文章(猜测我们来晚了),她在WWDC会话中进行了详细阐述(希望您单击该链接就使用Safari),以解决此问题。

此技术利用协议扩展。

  1. 创建一个类型以将我们的segue标识符表示为枚举
  Segues协议{ 
relatedtype SegueIdentifier:RawRepresentable
}

2.扩展协议,限制它只能在UIViewController上使用

 扩展Segues,其中Self:UIViewController,SegueIdentifier.RawValue ==字符串{ 
//方法来
}

3.添加一个接受我们的SegueIdentifier类型的performSegue方法,并将其rawValue传递给默认的performSegue方法

  func performSegue(withIdentifier标识符:SegueIdentifier,发件人:任何?){ 
performSegue(withIdentifier:identifier.rawValue,发送者:发送者)
}

4.添加一个函数,该函数返回给定UIStoryboardSegue SegueIdentifier类型

  func segueId(用于segue:UIStoryboardSegue)-> SegueIdentifier { 
守护
让标识符= segue.identifier,
让segueIdentifier = SegueIdentifier(rawValue:标识符)
否则{fatalError()}

返回segueIdentifier
}

我们最终得到这样的结果:

现在让我们看看如何清理我们的视图控制器…

首先,我们将在表视图控制器上编写一个扩展并声明我们的命令。

 扩展MoviesViewController:Segues { 
枚举SegueIdentifier:字符串{
案例pushMovie,addMovie
}
}

调用performSegue我们使用enum而不是字符串。

  performSegue(withIdentifier:.pushMovie,发送者:indexPath.row) 

然后,在prepare:for函数中,我们可以switchsegueId:for函数获得的segueId:for

我们的语法更好一些,编译器将确保我们处理所有segue情况。 但是,我们仍然需要强制转换,并且我们的视图控制器负责了解呈现的内容。

最好通过在枚举案例中获取视图控制器来消除强制转换( case .pushMovie(let movieVC) ),但是这给我带来了太多的实现头痛,因为它们无法消除糟糕as! 声明。 如果您实施了此操作,我将很乐意为您提供帮助。 🙏