Swift 4 新特性

  • #1.添加Codable协议,方便自定义数据类型序列化
    #2.添加定义多行字符串语法
    #3.改进key-value coding的keypath
    #4.修改并强化字典功能
    #5.字符串变为集合类型

    1.Swifty encoding and decoding:

    在Objective-C中值类型的相互影响是十分糟糕的。比如NSCoding协议,类继承它之后,我们需要在类中重写自定义的 encoding 和 decoding方法。这样显得十分痛苦而且很容易出错。
    在swift4.0 中,引入了新的Codable协议,可以让你在不添加其他特殊代码的情况下序列化和反序列化自定义的数据类型,从而不用担心值类型的丢失。更漂亮的是,你可以选择数据被序列化为什么样的格式:plist(XML)或者JSON。
    是的,Swift 4 可以让你在不添加任何特殊代码的情况下将自定义数据类型序列化为JSON。
    以代码为例:
    首先,我们自定义一个数据类型:

    struct Language:Codable {
        var name: String
        var version: Int
    }
    
    let swift = Language(name:"Swift",version:4)
    let php = Language(name:"PHP",version:7)
    let perl = Language(name:"Perl",version:6)
    

     

    让Language这个结构体遵从Codable协议,我们便可以将它转化为json格式的数据展示:

    let encoder = JSONEncoder()
    let encoded = try? encoder.encode(swift){
        //...
    }
    

    Swift将会自动编码你的数据类型中的所有属性。
    我们可以使用encode和decode方法来编码和解码对象:

    let encoder = JSONEncoder()
    let encoded = try? encoder.encode(swift)
    if encoded != nil {
        if let json = String(data: encoded!,encoding:.utf8){
            print(json)
        }
    }
    
    let decoder = JSONDecoder()
    if let decoded = try? decoder.decode(Language.self, from: encoded!)
    {
        print(decoded.name)
    }
    

     

    同样可以有PropertyList的encode和decode:

    //PropertyList
    let propertyListEncoder = PropertyListEncoder()
    let propertyListed = try? propertyListEncoder.encode(php)
    
    let propertyDecoder = PropertyListDecoder()
    if let value = try? propertyDecoder.decode(Language.self,from: propertyListed!)
    {
       print(value.name)
    }
    

     

    了解更多关于swift4.0 encode和decode的内容,可以参考链接:the Swift Evolution proposal for this new feature

    2.多行文字的字符串:

    之前我们可以通过使用"\n"来使字符串换行。比如:

    let beforeString = "When you write a string that spans multiple \nlines make sure you start its content on a  \nline all of its own, and end it with three \nquotes also on a line of their own. Multi-line strings also let you write \"quote marks\" \nfreely inside your strings, which is great!"
    //print(beforeString)
    

    这种方式阅读起来很不方便,看起来很不美观,不能直观的显示它所要呈现给用户展示的样子。
    在swift4.0中,提供了专门的语法来显示多行字符串,从而告别转义。

    let longString = """
    When you write a string that spans multiple
    lines make sure you start its content on a
    line all of its own, and end it with three
    quotes also on a line of their own.
    Multi-line strings also let you write "quote marks"
    freely inside your strings, which is great!
    """
    print(longString)
    

    语法说明:
    1.以三个双引号作为开始的标识。
    2.以三个双引号作为结束的标识。
    3.不管开始标识还是结束标识,都必须单独占据一行
    4.你定义的字符串就是开始标识和结束标识中间的样子

    了解更多可以参考链接:the Swift Evolution proposal for this new feature.

    3.改进key-value coding的keypath

    Swift中如何使用keypath呢?
    首先,我们定义两个结构体:

    struct Crew {
        var name: String
        var rank:String
    }
    struct Starship {
        var name: String
        var maxWarp: Double
        var captain: Crew
        func goToMaximumWarp(){
            print("\(name) is now travelling at warp \(maxWarp)")
        }
    }
    
    let janeway = Crew(name:"Kathryn Janeway",rank:"Captain")
    var voyager = Starship(name: "Voyager", maxWarp: 9.975, captain: janeway)
    let enterWarp = voyager.goToMaximumWarp
    enterWarp()
    

     

    在Swift中,我们可以给函数添加一个引用。比如,我们可以给goToMaximumWarp()方法添加一个叫做enterWarp的引用,之后我们便可以使用enterWarp来调用它。然而,我们却不能对属性做同样的操作。是的,我们不能给Starship的name属性添加一个引用。
    这个问题,可以通过使用keypath来解决:正如enterWarp()一样,它们是未被调用的属性引用。 如果您现在调用引用,则得到当前值,但如果稍后调用引用,则获得最新值。
    keyPath的语法格式为反斜杠:

    let nameKeyPath = \Starship.name
    let maxWarpKeyPath = \Starship.maxWarp
    let captainName = \Starship.captain.name
    

    之后你便可以在Starship的实例中使用它了:

    print(voyager[keyPath: nameKeyPath])  //Voyager
    voyager[keyPath: nameKeyPath] = "456"
    print(voyager.name)   //456
    voyager.goToMaximumWarp()  //456 is now travelling at warp 9.975
    enterWarp()  //Voyager is now travelling at warp 9.975
    
    let starshipName = voyager[keyPath: nameKeyPath]
    let starshipMaxWarp = voyager[keyPath: maxWarpKeyPath]
    let starshipCaptain = voyager[keyPath: captainName]
    

    想要了解更多,可以参考链接:the Swift Evolution proposal for this new feature

    4.改进了字典功能:

    Swift4.0 让Dictionary的功能更强大。
    在Swift3.0 中,Dictionary的filter函数会返回一个包含key/value元组的数组。
    比如:

    let cities = ["Shanghai": 24_256_800, "Karachi": 23_500_000, "Beijing": 21_516_000, "Seoul": 9_995_000];
    
    let massiveCities = cities.filter { $0.value > 10_000_000 }
    

    在Swift3.0中,你不能通过massiveCities["Shanghai"]来获取对应的值。因为massiveCities不是一个字典类型。只能通过massiveCities[0].value来获取。
    但在Swift4.0中,massiveCities是字典类型,使用massiveCities["Shanghai"]获取值完全没有问题。

    print(massiveCities["Shanghai"] ?? "nil Value");
    

    想要了解更多,可以参考链接:the Swift Evolution proposal for these new features.

    5.String 又变成了集合类型:

    这意味着,你可以做字符串倒置,循环获取每个字符,map(),flatMap()等操作。
    比如:

    let quote = "It is a truth universally acknowledged that new Swift versions bring new features."
    let reversed = quote.reversed()
    
    for letter in quote {
        print(letter)
    }
    
    

    另外,Swift4.0 中,引入类似于python中字符串的一些操作。在省略起始位置或者结束位置的情况下,可以自动推断集合的起始位置或者结束位置。

    let characters = ["Dr Horrible", "Captain Hammer", "Penny", "Bad Horse", "Moist"]
    let bigParts = characters[..<3]
    let smallParts = characters[3...]
    print(bigParts)    //["Dr Horrible", "Captain Hammer", "Penny"]
    print(smallParts)   //["Bad Horse", "Moist"]
posted @ 2018-05-23 10:39  Allence  阅读(515)  评论(0编辑  收藏  举报