美文网首页收藏swift
Swift开发小技巧系列 - 改造Optional

Swift开发小技巧系列 - 改造Optional

作者: DEREK_ZHOU | 来源:发表于2017-10-06 11:49 被阅读0次

    原文链接

    很多开发语言对nil这个概念,也都有不同的处理。Swift也一样,但处理方式有所不同。Swift语言很巧妙创造一种新的类型:Optional, 来修饰可以被赋值nil的变量。有了Optional,可以确保明确处理nil值,让你的程序更加安全。

    什么是Optional?

    我们先来看看源码

    public enum Optional<Wrapped> : ExpressibleByNilLiteral {
        case none
        case some(Wrapped)
    }
    

    从上面,我们可以看到,Optional是一种枚举类型。并且一种有关联值(Associated Value)枚举。

    如何使用Optional?

    当我们定义变量时,其实我们只有两种选择,一种是optional类型的,另一种是non-optional的。这两种具体有什么区别,我们看下面代码。

    // non-optional
    var message: String = "Hello, World!"  // 编译正常
    message = nil   // 编译出错
    
    // optional
    var name: String? = "Derek"  // 编译正常
    name = nil  // 编译正常
    

    从上面代码我们可以看出,non-optional类型的变量时不能被赋值nil的。String是non-optional类型,String?是optional类型,它们是两种不同的类型,String是表示字符串类型,String?本质上是枚举类型,只是这个枚举类型的关联值类型为StringSwift语言设计为了安全性,需要你在声明变量时,明确这个变量是否是Optional类型。Swift编译器会以此为依据,在编译期间做相应的检查。

    改造Optional

    在对Optional类型有了基本了解以后,我们来更进一步。来看看实际开发中,有哪些使用场景需要我们改造下Optional,来让写程序变得更简单些。

    场景一:获取UITextField里面的text,并判断是否为nilempty

    一般我们会这么写:

    guard let text = textField.text, !text.isEmpty else {
        // handle for nil or empty
        return 
    }
    
    // Do something with text
    

    因为UITextField的text属性的类型为String?,所有每次都要先解包(unwrap),再检查是否为空。需要两步,我们有没有办法一步解决呢?看下面代码

    extension Optional where Wrapped == String {
        public var nilIfEmpty: String? {
            guard let value = self else { return nil }
            return value.isEmpty ? nil : value
        }
    }
    
    guard let text = textField.text.nilIfEmpty else {
        // handle for nil or empty
        return 
    }
    
    // Do something with text
    

    其实我们的目的就是把nilempty当做同一种情况处理。这时候我们可以通过给Optional加一个计算属性nilIfEmpty,当Optional的值为nil或者empty时,这个属性都会返回nil。这样我们每次的处理代码,就只要使用一次解包(unwrap)操作就行了

    场景二: 把let names = ["Derek", "", "John", "", "Tony", nil] 里面名字为nilempty的过滤掉

    这个需求使用我们自定义的nilIfEmpty,实现起来非常简单,请看下面代码

    let names = ["Derek", "", "John", "", "Tony", nil]   // [String?]
    
    let validNames1 = names.map { $0.nilIfEmpty }  // [String?]
    print(validNames1) // [Optional("Derek"), nil, Optional("John"), nil, Optional("Tony"), nil]
    
    let validNames2 = names.flatMap { $0.nilIfEmpty } // [String]
    print(validNames2)  // ["Derek", "John", "Tony"]
    

    参考资料

    联系方式

    备注

    我们在软件开发的过程中,为了提高效率,其中很重要的一环就是把反复使用到的功能或模块封装起来。因此我在GitHub上开源了一个小工具集 - SwiftDevHints,来总结自己在实际项目开发过程中封装的一些小功能。

    刚刚介绍的只是其中一个小功能,想看看其它更多功能,请直接点击SwiftDevHints。如果您觉得对您有所帮助,请给一个star吧。

    相关文章

      网友评论

        本文标题:Swift开发小技巧系列 - 改造Optional

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