Swift 高级特性

Posted Lucky_William

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift 高级特性相关的知识,希望对你有一定的参考价值。

Swift 高级特性

一、Swift 独占访问

Swift 内存安全检查:当两个变量访问同一块内存时,会产生独占内存访问限制。
发生读写权限冲突的情况:

  1. inout 参数读写冲突
  2. 结构体中函数修改成员属性读写冲突
  3. 值类型属性读写冲突

1. inout 参数读写冲突


// 1. Swift inout 参数读写冲突
var inputStr = "input"
func plusSlef1(_ param: inout String) 
    // 在 >= Swift4 版本会抛异常:同时访问0x103ed30a0,但是修改需要独占访问。
    param += inputStr

// 调用下面的代码会崩溃
// plusSlef1(&inputStr)

// 同时访问同一个内存地址,造成读写冲突
func plusSlef2(_ param1: inout String, _ param2: inout String) 
    // 在 >= Swift4 版本会抛异常:重叠访问'inputStr',但修改需要独占访问;考虑复制到一个局部变量
    let result = param1 + param2
    print(result)

// 调用下面的代码会崩溃
// plusSlef2(&inputStr, &inputStr)


2. 结构体中函数修改成员属性读写冲突


// Swift 结构体中函数修改成员属性读写冲突
struct StructA 
    var field: Int
    
    // mutating 修饰可修改成员属性,inout 开放写访问,会产生读写冲突
    mutating func edit(_ param: inout StructA) 
        field = param.field
    


var structA = StructA(field: 100)
// 调用下面的代码会产生编译错误:
// 1. Inout参数不允许彼此别名
// 2. 重叠访问'structA',但修改需要独占访问;考虑复制到一个局部变量
// structA.edit(&structA)


3. 值类型属性读写冲突


// Swift 值类型属性读写冲突
class ClassA 
    // 定义元组,属于值类型
    var tuple = (key1: 1, key2 : 2)
    
    func test1(_ param1: inout Int, _ param2: inout Int) 
        print(param1, param2)
    
    
    func test2() 
        // 如果被调用会崩溃,同时访问0x600000667cd0,但是修改需要独占访问。
        test1(&tuple.key1, &tuple.key2)
    
    
    func test3() 
        // 访问 局部 值变量 可以正常使用
        var localTuple = (key1: 3, key2 : 4)
        test1(&localTuple.key1, &localTuple.key2)
    


let cla = ClassA()
// 调用下面的代码会崩溃
// cla.test2()
cla.test3() // 正常调用,打印 3 4


二、Swift 增强字符串

// 多行字符串 界定符 转义符
// Swift 多行字符串,同 kotlin 的原始字符串,不需要手动添加换行符。可用于排版
var text1 = """
start
\\(1)
2
end
"""
print(text1)


// 转义符
var text2 = "对单引号进行转义\\'"
print(text2) // 对单引号进行转义'

// 使用界定符代替转义符
var text3 = #"对单引号进行转义'"#
print(text3) // 对单引号进行转义'

// 使用界定符时,转义符失去作用
var text4 = #"换行符1 \\n 换行符2"#
print(text4) // 换行符1 \\n 换行符2

// 使用界定符时,使用 \\# 保留转义符的作用
var text5 = #"换行符1 \\#n 换行符2"#
print(text5) // 会换行打印: 换行符1 换行符2


三、Swift 动态成员查找


@dynamicMemberLookup // Swift使用 @dynamicMemberLookup 为类增加动态查找成员的能力
@dynamicCallable // Swift使用 @dynamicCallable 为类增加动态方法调用的能力
class Data 
    var field1: Int = 0
    var field2: String = ""
    
    subscript(dynamicMember member: Int) -> String 
        return "class don't have the field: \\(member), type int"
    
    
    subscript(dynamicMember member: String) -> String 
        return "class don't have the field: \\(member), type String"
    
    
    // 传入一组参数
    func dynamicallyCall(withArguments argArray: [Int]) 
        print("invoke unknown func with args: \\(argArray)")
    
    
    // 传入键值对参数
    func dynamicallyCall(withKeywordArguments pairs: KeyValuePairs<String, Int>) 
        let argPairs = pairs.map key, value in
            return "\\(key): \\(value)"
        
        print(argPairs)
    


let data = Data()
// 当访问不存在的属性时,就会调用对应的 subscript 方法返回对应类型的值
// class don't have the field: someInt, type String. class don't have the field: someString, type String
print(data.someInt, data.someString)


// 调用不存在的方法,把实例当做方法调用
// 传入一组参数
data(1, 2, 3) // invoke unknown func with args: [1, 2, 3]
// 传入键值对参数
data(key1: 1, key2: 2) // ["key1: 1", "key2: 2"]


四、Swift 增强协议


// Swift 使用多个协议界定参数
protocol ProtocolA 
    var field: String get set

protocol ProtocolB 
    func method()

// 实现多个协议
class ClassImpl : ProtocolA, ProtocolB 
    var field: String = "impl field"
    
    func method() 
        print("impl method")
    

// 使用 & 界定多个协议
func testImpl(impl: ProtocolA & ProtocolB) 
    print(impl.field)
    impl.method()


testImpl(impl: ClassImpl())


GitHub 源码:AdvancedFeatures.playground

以上是关于Swift 高级特性的主要内容,如果未能解决你的问题,请参考以下文章

swift常用代码片段

swift 代码片段

如何将这个 Objective-C 代码片段写入 Swift?

如何使用 Swift 使用此代码片段为 iOS 应用程序初始化 SDK?

传递额外的值 Passing Extra Values |在视图中生成输出URL | 高级路由特性 | 精通ASP-NET-MVC-5-弗瑞曼

JavaScript笔试题(js高级代码片段)