前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【iOS 开发】想一下再用 guard

【iOS 开发】想一下再用 guard

作者头像
KyXu
发布2019-04-11 16:32:46
3800
发布2019-04-11 16:32:46
举报
文章被收录于专栏:KyXuKyXu

自从知道了 <code>guard let</code> 这种写法之后,我就几乎换掉了所有 <code>if let</code> 写法。但今天要提醒一下,使用 <code>guard let</code> 之前,需要先思考一下,因为这并不总是万全的解放方案。

代码语言:javascript
复制
// bad
func createMan0(name: String?, country: String?, age: Int?) -> Man? {
    if let name = name {
        if let country = country {
            if let age = age {
                return Man(name: name, country: country, age: age)
            }
        }
    }
    return nil
}

// good
func createMan1(name: String?, country: String?, age: Int?) -> Man? {
    guard let name = name else { return nil }
    guard let country = country else { return nil }
    guard let age = age else { return nil }
    return Man(name: name, country: country, age: age)
}

如上的代码是很常见的 <code>guard let</code> 使用场景,为了避免让我们写出 “Swift 鞭尸金字塔”。

代码语言:javascript
复制
enum NetworkState {
    case Cellular
    case Wifi
}

func test(state:NetworkState) {
    switch state {
    case .Cellular:
        guard let speed = networkSpeed else {return}
        print("Cellular Speed: \(speed)")
    case .Wifi:
        guard let speed = networkSpeed else {return}
        print("Wifi Speed: \(speed)")
    }
    // 可能无法被执行
    doSomething()
}

test(.Cellular)

但这种情况下,如果我们一看到 <code>networkSpeed</code> 是可选型的,就决定使用 <code>guard ... else {return}</code> 语法,那么会出现的结果就是一旦 <code>networkSpeed</code> 值为 <code>nil</code> , <code>doSomething()</code> 将不会被执行。我们一开始可能仅仅是希望无法获取网速数值的时候,不在控制台打印相应信息,但现在整个 <code>test()</code> 都被提前退出了。解决这个问题很简单,把 <code>guard ... else {return}</code> 改成 <code>guard ... else {break}</code>,让 <code>switch - case</code> 里面的代码段提前退出就可以了。

但是并不一定每种情况我们都要回避使用 <code>guard ... else {return}</code>

代码语言:javascript
复制
enum File {
    case Pages
    case Keynote
}

func saveInBackground( completion: File->Void ) {
    completion(.Pages)
}

func closureTest() {
    saveInBackground( { file in
        switch file {
        case .Pages:
            guard let name = fileName else {return}
            print("Pages: \(name)")
        case .Keynote:
            guard let name = fileName else {return}
            print("Keynote: \(name)")
        }
    })
    // 一定会被执行
    doSomething()
}

closureTest()

这种情况下,<code>return</code> 所退出的方法是 <code>saveInBackground</code> 函数里面的闭包 <code>completion: File->Void</code>,<code>saveInBackground</code> 本身不受影响,如果 <code>saveInBackground</code> 里面还有其他参数是闭包,那么其他闭包自然也不受影响。

代码语言:javascript
复制
func configureButton(button:UIButton, buttonTitle:String?, buttonImage:UIImage?) {
    if let title = buttonTitle {
        button.setTitle(title, forState: .Normal)
    }
    if let image = buttonImage {
        button.setImage(image, forState: .Normal)
    }
}

而在这种情况,<code>if let</code> 语法就很自然,有 title 我们就设置 title,有 image 我们就设置 image,没有就算了,总不能说没有 title 或 image 就直接放弃当前的方法,或许我们后面还要做很多其他事情。


没东西了

希望大家在使用 <code>guard</code> 关键字的时候多思考一下,以免犯下低级错误。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.07.18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 没东西了
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档