Swift学习Swiftswift

Swift5.0新特性更新

2019-01-28  本文已影响24人  TitanCoder
Swift

新特性

dynamicCallable

func dynamicallyCall(withArguments args: [Int]) -> Double

func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double

下面看一个例子, RandomNumberGenerator生成一个随机数

Swift 5.0之前的定义和调用方式

// 定义方式
struct RandomNumberGenerator {
    func generate(numberOfZeroes: Int) -> Double {
        let maximum = pow(10, Double(numberOfZeroes))
        return Double.random(in: 0...maximum)
    }
}


// 调用方式
let random = RandomNumberGenerator()
let num = random.generate(numberOfZeroes: 2)
print(num)

Swift 5.0使用@dynamicCallable属性

// 定义方式
@dynamicCallable
struct RandomNumberGenerator {
    func dynamicallyCall(withArguments args: [Int]) -> Double {
        let numberOfZeroes = Double(args.first ?? 0)
        let maximum = pow(10, numberOfZeroes)
        return Double.random(in: 0...maximum)
    }
}


// 调用方式
let random = RandomNumberGenerator()
let num = random(2)
// random(2)等同于random.dynamicallyCall(withArguments: [2])
print(num)

WritableKeyPath

let id = \Int.self  
var x = 1
print(id)   ////Swift.WritableKeyPath<Swift.Int, Swift.Int>
x.self = 2
print(x)   //2
print(x.self)  //2

print(x[keyPath: id])  //2
x[keyPath: id] = 3
print(x[keyPath: id])  //3

可选参数

Swift 5之前,可以编写一个带有可变参数的枚举, 但是在Swift 5开始, 调用时会报错, 如下

enum X {
    // 此处定义切没有调用时不会报错
    case foo(bar: Int...) 
}

func baz() -> X {
    // 此处调用时会报错
    return .foo(bar: 0, 1, 2, 3) 
} 

Swift 5之后, 上述定义改成数组参数, 而不是可变参数, 如下

enum X {
    case foo(bar: [Int]) 
} 

func baz() -> X {
    return .foo(bar: [0, 1, 2, 3]) 
} 

Raw Strings

\处理

// 文字引用类型
// 错误写法
let quote = "Alice: "How long is forever?" White Rabbit: "Sometimes, just one second.""
// 正确写法
let quote1 = "Alice: \"How long is forever?\" White Rabbit: \"Sometimes, just one second.\""


// 正则表法式类型
// 错误写法
let ucCaseCheck = "enum\s+.+\{.*case\s+[:upper:]"
// 正确写法
let ucCaseCheck = "enum\\s+.+\\{.*case\\s+[:upper:]"

#处理

let rain = #"The "rain" in "Spain" falls mainly on the Spaniards."#

let keypaths = #"Swift keypaths such as \Person.name hold uninvoked references to properties."#

let answer = 42
let dontpanic = #"The answer to life, the universe, and everything is \#(answer)."#

注意: 上面使用\#(answer)引用变量而不是\(answer), 因为在用#包裹的字符串中反斜杠将会被失败别为文字字符而不是转义字符, 所以必须额外的添加#

##处理

let str = ##"My dog said "woof"#gooddog"##

多行字符串

原始字符串与Swift的多行字符串系统完全兼容 - 只需用于#"""启动,然后"""#结束

let multiline = #"""
    The answer to life,
    the universe,
    and everything is \#(answer).
    """#

try?嵌套

先看下面代码

struct User {
    var id: Int

    init?(id: Int) {
        if id < 1 {
            return nil
        }

        self.id = id
    }

    func getMessages() throws -> String {
        // complicated code here
        return "No messages"
    }
}

Swift4.2及其之前的版本中

let user = User(id: 1)
// 这里得到的message的类型是: let messages: String??
let messages = try? user?.getMessages()

// 如果我们想得到非可选值就需要
print((messages ?? "") ?? "")
// 或者多次强解, 当然不建议强解写法
print(messages!!)
let user = User(id: 1)
// 类型: let messages: String?
let messages = try? user?.getMessages()

print(messages ?? "")

isMultiple

let rowNumber = 4

if rowNumber.isMultiple(of: 2) {
    print("Even")
} else {
    print("Odd")
}

// 该方法等效于
if rowNumber % 2 == 0 {}

count

let arr = [1, 2, 34, 5, 6, 7, 8, 12, 45, 6, 9]

let filter = arr.filter({ $0 > 10 })
print(filter)  //[34, 12, 45]

let count = arr.count(where: { $0 > 10 })
print(count)  // 3

compactMapValues

let times = [
    "first": 2,
    "second": 43,
    "three": 12,
    "four": 3
]

let compact = times.compactMap({ $0.value > 10 })
print(compact)
// [true, false, true, false]

let mapValues = times.mapValues({ $0 + 2 })
print(mapValues)
// ["second": 45, "first": 4, "three": 14, "four": 5]
let times1 = [
    "Hudson": "38",
    "Clarke": "42",
    "Robinson": "35",
    "Hartis": "DNF"
]

let comMap2 = times1.compactMapValues({ Int($0) })
print(comMap2)
// ["Clarke": 42, "Robinson": 35, "Hudson": 38]

SubSequence

// swift 5不在支持
extension Sequence {
    func dropTwo() -> SubSequence {
        return self.dropFirst(2)
    }
}


// 建议改为
extension Sequence {
    func dropTwo() -> DropFirstSequence<Self> { 
        return self.dropFirst(2)
    }
}

// 或者
extension Collection {
    func dropTwo() -> SubSequence {
        return self.dropFirst(2)
    }
}

其他相关更新

SE-0214

DictionaryLiteral类型重命名为KeyValuePairs

SE-0238

SE- 0236

SR-695

Swift 5中不再支持返回Self的类方法

// 不在支持
class Base { 
    class func factory() -> Self { /*...*/ }
} 

SR-631

不同文件中的扩展名无法相互识别

class FirstClass { }

extension FirstClass {
    class SecondClass { }
}

// 这里将会报错: "SecondClass is not a member type of FirstClass"
extension FirstClass.SecondClass { 
    class ThirdClass { }
}

SR-7251

Swift 5中, 在所声明的类里面, 所声明的变量名不能和类名一样

struct S {}
extension S {
  static var i: Int { return 0 }
  struct i {} // error: “i”的声明无效
}

// 下面的方式是没有问题的
struct S1<T> {}
extension S1 {
  static var i: Int { return 0 }
  struct i {} // This is fine!
}

参考文献


上一篇下一篇

猜你喜欢

热点阅读