用枚举简化登录操作

作者: 八条8tiao | 来源:发表于2016-07-29 09:58 被阅读517次

今天的内容翻译自Simplifying Login with Swift Enums,隐隐约约的记得好像有人翻译过这篇内容,我本来对这篇内容不是很感兴趣,但无意中发现了另外一篇博文指出:《Simplifying Login with Swift Enums》这么做并不好,所以我的兴趣就来了,我准备把两篇内容都整理一下,今天先发这一篇。首先要推荐大家看原文,我这里并没有逐句的对照翻译,我是按照自己的理解重新把内容整理了一遍。如果有出现不正确的地方欢迎大家留言给我。

原作者David East根据自己的经验得出一个结论:一款app在登录操作上,如果想获得用户的信任和好评,那么需要为用户提供选择,提供多种登陆方式。David East认为swift的枚举可以有效的对登录逻辑进行抽象,从而令我们能够保持view controllers的干净简洁。我自己确认为这篇内容做为enum的基本介绍是比较合适的。

使用枚举定义社交账号登录

enum LoginProvider {
  case Facebook
  case Email
  case Google
  case Twitter
}

很多语言的枚举只是出于类型安全的考虑而把普通类型打个包而已,而swift中的枚举则是一个实实在在的 first-class,枚举中每一个case都是一个fully-fledged value,例如:Facebook 的类型就是LoginProvider。

枚举的Raw Values

我们可以给枚举的每一个case存储一个值,我们把这种值称作枚举的Raw Values。

enum LoginProvider: String {
  case Facebook = "facebook"
  case Email = "email"
  case Google = "google"
  case Twitter = "twitter"
}

对于Raw Values我们应该关注几件事情:

  • Raw Values要求枚举的定义是有明确的返回类型,我们这里是 String
  • 枚举的每个case的类型必须是一致的
  • 我们可以通过rawValue来初始化一个枚举,参数名称就是rawValue
let provider = LoginProvider.init(rawValue: "email")

通过定义的rawValue “email”,我们可以获得一个 Email,这个确实很方便。

Associated Values

rawValue实际上是给枚举的每个case做了一个常量的预设值,那我们可不可以给每个case绑定一个变量值呢?这样的话我们就可以非常方便的给以枚举根据特定情况绑定不同的值了。幸运的是,swift确实提供这个能力:Associated Values

enum LoginProvider {
  case Facebook
  case Email(String, String)
  case Google
  case Twitter
}

let provider = LoginProvider.Email("bob@bob.com", "pass")

关于Associated Values我们可以关注几件事情:

  • 每个case的类型可以不同,各自根据各自的需要使用类型
  • 枚举的定义上面没有返回值了
  • Associated Values可以是任意类型

我们可以定义一个user类型,然后作为枚举的Associated Values。

struct LoginUser {
  let email: String
  let password: String
  func isValid() -> Bool {
    return email != "" && password != ""
  }
}


enum LoginProvider {
  case Facebook
  case Email(LoginUser)
  case Google
  case Twitter
}

有了这样的定义之后,我们就可以创建一个Email枚举了.

let provider = LoginProvider.Email(user)

在Associated Values特性的帮助下,枚举可以“渗透到”各种问题的解决方案中去,而不会因为关联类型问题而被拒之门外。

case where

原作者说:正是因为有Associated Values特性的存在,才显得case where特别的甜。

let provider = LoginProvider.Email(user)

switch provider {
  case let .Email(user) where user.isValid():
    // login!
    break
  case let .Email(user) where !user.isValid():
    // don’t login!
    break
}

case let 首先对Email进行了值绑定(把user对象抽出来),然后使用使用where关键字引入的条件表达式,对逻辑进行了一步处理。switch与枚举的配合确实相当完美(和Tuples也类似)。

Functions

说case where还只是一个铺垫,毕竟我们是在这里赞美枚举吗,switch再好也不是枚举的内容啊。无需感到遗憾,枚举内可以定义function,可以整合所有你需要的内容。

enum LoginProvider {
    case Facebook
    case Email(LoginUser)
    case Google
    case Twitter
    
    func login() {
        switch self {
        case let .Email(user) where user.isValid():
            // login!
            break
        default:
            break
        }
    }
}

我们在枚举中定义方法以后,我们的登录方案就显得很完整了,而且非常的简洁。

var lp = LoginProvider.Email(user)
lp.login()

关于这部分内容并没有结束,因为反对意见还没有出场,如果感兴趣可以关注我的下一篇内容:这样做并不怎么好。

** 原作者非常看重枚举能够把不同的内容整合在一起并体现统一的类型。如果没有枚举的帮助,在统一各种不同的登录SDK上面,我们确实需要在协议和实现上面花不少功夫,而且枚举提供非常棒的特性,能够进一步抽象业务逻辑,总之swift的枚举是非常值得点赞的**

相关文章

网友评论

  • key3board:不是很明白枚举,里面加方法。然后 funcation login 里面做业务吗?

本文标题:用枚举简化登录操作

本文链接:https://www.haomeiwen.com/subject/jlhzjttx.html