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)
}