1: 运行下面代码中的变量len值是多少? 为什么?
var array1 = [1, 2, 3, 4, 5]
var array2 = array1
array2.append(6)
var len = array1.count
解答:
变量 len的值是 5 ,也就是说array1只有5个元素,而array2有6个元素。
array1 = [1, 2, 3, 4, 5]
array2 = [1, 2, 3, 4, 5, 6]
当把变量array1赋值给array2的时候,会创建一份array1的复制,然后复制给array2。
背后的原因是Swift数组是值类型(底层是structs),而不是引用类型(类),当把一个值赋值给一个变量时,当给方法和函数传递参数时,都是创建一份新的复制然后赋值或传递。
Swift的值类型包括:
- 结构体 (数字和字典)
- 枚举
- 基本数据类型 (boolean, integer, float等)
2: 下面的代码有什么问题? 如何修复?
class Master {
lazy var detail: Detail = Detail(master: self)
init() {
println("Master init")
}
deinit {
println("Master deinit")
}
}
class Detail {
var master: Master
init(master: Master) {
println("Detail init")
self.master = master
}
deinit {
println("Detail deinit")
}
}
func createMaster() {
var master: Master = Master()
var detail = master.detail
}
createMaster()
解答:
Master和Detail之间存在循环引用,在创建Master对象的时候,会创建Detail实例并持有它,而在创建Detail的时候,需要把Master对象赋值给Detail,并被持有引用。
众所周知,循环引用会导致内存泄露,解决的思路就是打破循环引用。
Swift中为此提供了两个关键字修饰符 weak 和 unowned, 需要注意两者的区别:
- unowned: 假设引用对象在生命周期总是存在,这样其属性声明是非可选类型。
- weak: 对象在预见时间内可能为空,这样属性只能为可选类型。
根据上面的原则,只需把Detail内对Master的引用设置为unowned即可:
class Detail {
unowned var master: Master
...
}
3: 下面代码中有什么问题? 如何修复?
var defaults = NSUserDefaults.standardUserDefaults()
var userPref = defaults.stringForKey("userPref")!
printString(userPref)
func printString(string: String) {
println(string)
}
解答:
上述代码中的方法NSUserDefaults.stringForKey 返回的值是可选类型,不能确定‘userPref’能查询到值,也不能确定查询到的值能转换成string类型。
如果根据‘userPref’不能查询到值,或查询到的值不能转换成string类型,都会导致程序崩溃,也就是说强制拆包操作针对可选值是可能失败的。
而解决方式就是确定强制拆包操作之前可选值不是nil。
let userPref = defaults.stringForKey("userPref")
if userPref != nil {
printString(userPref!)
}
更合理的修复方式:
if let userPref = defaults.stringForKey("userPref") {
printString(userPref)
}
网友评论