当Swift中的lazy、weak碰上NSObject

前言 Hi Coder,我是 CoderStar! 今天给大家介绍一个我遇到的小坑。过程大概是这样的,一个复用页面通过不同的入口进入,等返回时,有的正常,有的却出现了 Crash,log 信息如下。 Cannot form weak reference to instance XXXXXX. It is possible that this object was over-released, or is in the process of deallocation. 然后看了一下 Crash 时候的调用栈,发现崩溃在 deinit 时 KVO 释放 Observer 的过程中。一段排查之后,新的坑点出炉了。 具体业务代码就不贴了,贴一个能触发 Bug 的 Demo 吧(不包含使用合理性,仅用来测试 Crash)。 问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 protocol MyServiceDelegate: AnyObject {} class MyService { weak var delegate: MyServiceDelegate? func stop() {} } class MyClass: NSObject, MyServiceDelegate { private lazy var service: MyService = { let service = MyService() service.delegate = self return service }() deinit { service.stop() } } // 测试 func test() { let myClass = MyClass() } 大家觉得这段代码会发生什么?可能大家看了上面的介绍心中已经有了预想的答案。是的,跟上面 Crash 报错信息一致。 ...

November 21, 2024 · 3 min · 444 words · CoderStar

从SIL角度看Swift中的值类型与引用类型

前言 Hi Coder,我是 CoderStar! 在 Swift 开发过程中,你很可能至少问过自己一次 struct 与 class 之间的区别,即使你自己没问过,你的面试官应该也问过。对这个问题的答案中,可能最大的区别就是一个是值类型,而另一个是引用类型,今天我们就来具体聊聊这个区别。 那在介绍值类型与引用类型之前,我们还是先来回顾一下 struct 与 class 之间的区别这个问题。 class & struct 在 Swift 中,其实 class 与 struct 之间的核心区别不是很多,有很多区别是值类型与引用类型这个区别隐形带来的天然的区别。 class 可以继承,struct 不能继承(当然 struct 可以利用 protocol 来实现类似继承的效果。);受此影响的区别有: struct 中方法的派发方式全都是直接派发,而 class 中根据实际情况有多种派发方式,详情可看 Swift派发机制; class 需要自己定义构造函数,struct 默认生成; struct 默认生成的构造函数必须包括所有成员参数,只有当所有参数都为可选型时,可直接不用传入参数直接简单构造,class 中的属性必须都有默认值,否则编译错误, 可以通过声明时赋值或者构造函数赋值两种方式给属性设置默认值。 class 是引用类型,struct 是值类型;受此影响的区别有: struct 改变其属性受修饰符 let 影响,不可改变,class 不受影响; struct 方法中需要修改自身属性时 (非 init 方法),方法需要前缀修饰符 mutating; struct 因为是值类型的原因,所以自动线程安全,而且也不存在循环引用导致内存泄漏的风险; … 更多看下一章节 … 在 Swift 中,很多基础类型,如 String,Int 等等,都是使用 Struct 来定义。对于如何选择两者这个问题上,Apple 在一些官方文档中也给出了它们之间的区别以及官方建议。 ...

November 21, 2024 · 8 min · 1573 words · CoderStar

Swift开发规范

前言 代码的字里行间流淌的是软件生命中的血液,质量的提升是尽可能少踩坑,杜绝踩重复的坑,切实提升质量意识。另外,现代软件架构都需要协同开发完成,高效协作即降低协同成本,提升沟通效率,所谓无规矩不成方圆,无规范不能协作。众所周知,制订交通法规表面上是要限制行车权,实际上是保障公众的人身安全。试想如果没有限速,没有红绿灯,谁还敢上路行驶。对软件来说,适当的规范和标准绝不是消灭代码内容的创造性、优雅性,而是限制过度个性化,以一种普遍认可的统一方式一起做事,提升协作效率。– 摘自《阿里巴巴 Java 代码规范》 该开发规范会持续更新,请关注该 博文链接。 规约分为【强制】、【推荐】两大类。说明 对内容做了引申和解释;正例 给出正确的代码示例;反例 给出错误的代码示范; 命名规约 【强制】代码中的命名严禁使用拼音及英文混合的方式,更不允许直接出现中文的方式,最好也不要使用下划线或者美元符号开头; 1 反例:_name $name / 学生 / getPingfenByName()[评分] 【强制】文件名、class、struct、enum、protocol 命名统一使用 UpperCamelCase 风格; 1 2 正例:class LoginName { } / enum SexType { } 反例:class loginName { } / enum SexTYPE { } 【强制】方法名、参数名、成员变量、局部变量、枚举成员统一使用 lowerCamelCase 风格 1 2 正例:localValue / getMessageInfo() 反例:LocalValue / GetMessageInfo() 【强制】命名中出现缩略词时,缩略词要么全部大写,要么全部小写,以首字母大小写为准,通用缩略词包括 JSON、URL、ID 等; 1 2 正例:class IDUtil {} / func idToString() 反例:class IdUtils {} / func iDToString() 【强制】不要使用不规范的缩写,力求语义表达完整清楚,能直观的表达意图,不怕名称长; ...

November 16, 2024 · 5 min · 1041 words · CoderStar