Swift中面向协议的Segue Identifiers
2016-05-03 15:48
501 查看
8月份时候,我看了Swift in Practice WWDC15 Session这个视频,视频的第一部分给我的印象非常深刻,为此我写了一篇博文–A Beautiful Solution to Non-Optional UIImage Named in Swift。现在终于抽出时间针对视频的第二部分以及其他更多有趣的地方写篇文章了。
这篇文章是关于如何优雅地处理多个Segue Identifiers的。你猜对了–使用协议。
不幸的是,Segue Identifiers(跳转标识符)是基于字符串的硬编码。当你在Storyboard中添加它们的时候,在每一处相关的代码你都要把这串字符复制过去,拼写错误很可能就会发生。
如果将来你决定更改segue identifier的名称,那你必须在硬编码字符串的每个地方进行修改…这就可能导致潜在的复制粘贴错误或者拼写错误的危险。
为了缓和这种情况,凡是在ViewController中使用1个以上segue identifier时,我都用枚举(enum)来解决这种问题。
但是那也会造成另外一系列的问题,主要是太过臃肿和丑陋
在prepareForSegue中处理时,问题会变得更加严重
这是我在Swift2.0之前真实的代码。现在你至少可以使用guard来处理,但是仍然不够理想:
无论如何,在整个APP的每一个视图控制器中,你都必须解决这个问题,那么你清除这个问题呢?如开篇提到的–使用协议来解决这个问题。
解决方案
这个解决方案非常优雅,不过并不是我想出来的。感谢苹果在15WWDC上关于架构的演讲。严格来讲,这些简直棒极了。
首先,你创建一个SegueHandlerType,它将SegueIdentifier枚举标识为一个类型:
现在你可以使用功能强大的协议扩展为UIViewController对象创建基于字符串的SegueIdentifier枚举:
注意在协议扩展中的方法并没有在协议中声明–它们并不表示被重写(overrider)。
这是我见过的最好的使用实例。现在,使用起来非常简单和美观
结论
从视频中可以看到使用SegueHandlerType的好处包括:
当新添加segue没有被处理的时候,编译器就会报错
重用性
简洁的语法
我们同时也看到了协议的强大
使用协议以及关联类型来加强应用约束
通过一个被约束的协议扩展来共享实现
这篇文章是关于如何优雅地处理多个Segue Identifiers的。你猜对了–使用协议。
不幸的是,Segue Identifiers(跳转标识符)是基于字符串的硬编码。当你在Storyboard中添加它们的时候,在每一处相关的代码你都要把这串字符复制过去,拼写错误很可能就会发生。
@IBAction func onRedPillButtonTap(sender:AnyObject) { performSegueWithIdentifier("TheRedPillExperience", sender:self) }
如果将来你决定更改segue identifier的名称,那你必须在硬编码字符串的每个地方进行修改…这就可能导致潜在的复制粘贴错误或者拼写错误的危险。
为了缓和这种情况,凡是在ViewController中使用1个以上segue identifier时,我都用枚举(enum)来解决这种问题。
enum SegueIdentifier: String { case TheRedPillExperience case TheBluePillExperience }
但是那也会造成另外一系列的问题,主要是太过臃肿和丑陋
// ViewController.swift @IBAction func onRedPillButtonTap(sender:AnyObject) { performSegueWithIdentifier(SegueIdentifier.TheRedPillExperience.rawValue, sender:self) }
在prepareForSegue中处理时,问题会变得更加严重
这是我在Swift2.0之前真实的代码。现在你至少可以使用guard来处理,但是仍然不够理想:
override func prepareForSegue(segue:UIStoryboardSegue,sender:AnyObject?) { guard let identifier = segue.identifier, segueIdentifier = SegueIdentifier(rawValue:idnetifier) else { fatalError("Invalid segue identifier\(segue.identifier)") } switch segueIdentifier { case .TheRedPillExperience: print("��") case .TheRedPillExperience: print("��") } }
无论如何,在整个APP的每一个视图控制器中,你都必须解决这个问题,那么你清除这个问题呢?如开篇提到的–使用协议来解决这个问题。
解决方案
这个解决方案非常优雅,不过并不是我想出来的。感谢苹果在15WWDC上关于架构的演讲。严格来讲,这些简直棒极了。
首先,你创建一个SegueHandlerType,它将SegueIdentifier枚举标识为一个类型:
import UIKit import Foundation protocol SegueHandlerType { typealias SegueIndentifier:RawRepresentable }
现在你可以使用功能强大的协议扩展为UIViewController对象创建基于字符串的SegueIdentifier枚举:
// SegueHandlerType.swift extension SegueHandlerType where Self: UIViewController, SegueIdentifier.RawValue == String { func performSegueWithIndentifier(segueIdentifier: SegueIdentifier, sender: AnyObject?) { performSegueWithIdentifier(segueIdentifier.rawValue, sender: sender) } func segueIdentifierForSegue(segue: UIStoryboardSegue)->SegueIdentifier { guard let identifier = segue.identifier, segueIdentifier = SegueIdentifier(rawValue:identifier) else { fatalError("Invalid segue identifier\(segue.identifier).") } return segueIdentifier } }
注意在协议扩展中的方法并没有在协议中声明–它们并不表示被重写(overrider)。
这是我见过的最好的使用实例。现在,使用起来非常简单和美观
import UIKit class ViewController:UIViewController,segueHandlerType { enum SegueIdentifier:String { case TheRedPillExperience case TheBluePillExperience } override func viewDidLoad() { super.viewDidLoad() } override func prepareForSegue(segue:UIStoryboardSegue, sender:AnyObject?) { switch segueIdentifierForSegue(segue) { case .TheRedPillExperience: print("��") case .TheRedPillExperience: print("��") } } @IBAction func onRedPillButtonTap(sender:AnyObject) { performSegueWithIdentifier(.TheRedPillExperience, sender:self) } }
结论
从视频中可以看到使用SegueHandlerType的好处包括:
当新添加segue没有被处理的时候,编译器就会报错
重用性
简洁的语法
我们同时也看到了协议的强大
使用协议以及关联类型来加强应用约束
通过一个被约束的协议扩展来共享实现
相关文章推荐
- Apple Swift学习教程
- 介绍 Fedora 上的 Swift
- Swift中实现点击、双击、捏、旋转、拖动、划动、长按手势的类和方法介绍
- Swift自定义iOS中的TabBarController并为其添加动画
- Swift编程中的泛型解析
- Swift中定义二维数组的方法及遍历方法示例
- 简单分析Swift语言的一些基本特征
- 使用 Swift 语言编写 Android 应用入门
- Swift与C语言指针结合使用实例
- Swift心得笔记之控制流
- 用Swift构建一个简单的iOS邮件应用的方法
- 苹果公司推出的新编程语言Swift简介和入门教程
- Swift实现iOS应用中短信验证码倒计时功能的实例分享
- 探讨Swift数组和字典
- Swift中的指针操作和使用详细介绍
- Swift中使用正则表达式的一些方法
- Swift心得笔记之运算符
- Swift中使用可选类型完美解决占位问题
- Swift学习笔记之构造器重载