Swift高级特性(swift分析方法)
一、Swift 独占访问
Swift 内存安全检查:当两个变量访问同一块内存时,会产生独占内存访问限制。 发生读写权限冲突的情况:
inout 参数读写冲突
结构体中函数修改成员属性读写冲突
值类型属性读写冲突
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())复制代码
小结
不积跬步无以至千里,不积小流无以成江海。学习的过程总是痛苦的,学习的结果总是快乐的。但愿我们在顶端见,不妨点赞关注一下。
作者:iOS小王
链接:https://juejin.cn/post/7035877254546587655