Swift-Initialization

更新 發佈閱讀 11 分鐘

swift讀書筆記

Documentation
Edit descriptiondocs.swift.org

objective-c 的init 會return value,swift 不會。

所有的property都必須在Init()裡面設定初始值,或設定stored property,這種情況給值下不會觸發property observers。如果是初始化時沒辦法確定值,或可能為nil,型別可設成?

如果property值不會改變的話,建議直接給一個預設值,而不是在Init()裡設定。這種做法讓init()、deinit()都更簡潔。

特殊寫法:在init的時候assign constant property

class SurveyQuestion {
let text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}

概念近似於Flutter的final,由於實際上是常數,只能賦值一次。

Flutter final與const的差異

Constant

Value must be known at compile-time, const birthday = "2008/12/25"
Can’t be changed after initialized.

FINAL

Value must be known at run-time, final birthday = getBirthDateFromDB()
Can’t be changed after initialized.

Default Initializer

任何class和struct都會有至少一個initializer(沒特別寫就是default)。default initializer創造新的instance並對裡面的property 賦值。

class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()

Memberwise initializers for struct

如果沒有寫custom init的方法,struct會自動產生memberwise initializer。

struct Size {
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)

當呼叫memberwise initializer時,可以省略任何具有預設值的property的值。在上面的範例中,struct Size的屬性都有預設值。可以任意省略其中一個屬性或兩個屬性,並且initializer將使用省略的預設值。例如:height width

let zeroByTwo = Size(height: 2.0)
print(zeroByTwo.width, zeroByTwo.height)
// Prints "0.0 2.0"


let zeroByZero = Size()
print(zeroByZero.width, zeroByZero.height)
// Prints "0.0 0.0"

class 如何使用 memberwise initializer??

Xcode > 選取class

Refactor > Generate Memberwise Initializer

Initializer delegation

initializer可以呼叫其他的initializer來完成初始化,避免重複的code。

Value types比較單純,因為不支援繼承,所以只能呼叫自己提供的initializer,可以使用self.init來呼叫其他initializer。Class 的initialization 必須確保繼承來的property也完成初始化。

如果value types寫了custom initializer,就不能再存取default / memberwise initializer。這是避免有其他人用成自動產生的initializer就跳過在custom initializer的額外設定。如果想要三種都保留的話,可以把custom initializer寫在extension裡。

raw-image

沒特別寫有自動產生default 和 memberwise兩種init 方法

raw-image

只剩custom init

raw-image

把custom init寫在extension,集滿三種init

Class Initializations: Designated Initializers and Convenience Initializers

Designated initializers 是 class主要的 init方法,通常情況只會有一個。但也有可能從superclass繼承來,就會有多個。任何class都必須最少有一個。

Convenience initializers 是 class 次要的 init方法,可以用他來呼叫Designated initializers。不一定要有。

初始化代理流程

  1. designated initializer必須呼叫上層的designated initializer。

2. convenience initializer 只能呼叫同一個層級的initializer。

3. convenience initializer最終必須呼叫designated initializer。

A simple way to remember this is:

  • Designated initializers 方向往上
  • Convenience initializers 橫向發展
raw-image

兩階段初始化

class初始化有兩階段。第一階段,先把所有stored property賦予初始值。第二階段,每個class在形成instance前,可以自訂自己的property值。兩階段是確保不會有property在初始化結束前就被存取,同時也確保property的值不會意外的被其他init改掉。

意外的小知識:objc跟swift很像都是二階段初始化,差別是objc第一階段全部塞0或nil。

第一階段

*先呼叫class的initializer

*分配記憶體給等下的instance。這時候還在準備中。

*designated initializer確保所有的property都有值。分配給這部分的property的記憶體已準備好。

*designated initializer往上☝️交給上層的designated initializer重複剛剛的任務,一直到最上層的class。

*到頂端後,所有的property都已經有值,instance的記憶體也準備完成。第一階段結束。

raw-image

第二階段

*從上往下,每個designated initializer都有自訂instance的空間。這個時機點可以存取self、修改property、呼叫instance method。

*最後!!換convenience initializer自訂instance&存取self。

raw-image

繼承Initialization

只能繼承designated initializer,不能繼承convenience initializer。如果subclass的convenience initializer跟superclass一樣,那這個subclass就永遠無法直接call到superclass的convenience initializer。

Failable Initializer

init keyword (init?)

在失敗的時候創造一個optional的type。雖然寫法是return nil,成功的時候不必寫return 物件。因爲嚴格來說,initialization並沒有真正return東西。不能同時存在同參數的init和init?。

Creates an integer from the given floating-point value, if it can be represented exactly.

init?(exactly source: Double)
let wholeNumber: Double = 12345.0
let pi = 3.14159


if let valueMaintained = Int(exactly: wholeNumber) {
print("\(wholeNumber) conversion to Int maintains value of \(valueMaintained)")
}
// Prints "12345.0 conversion to Int maintains value of 12345"


let valueChanged = Int(exactly: pi)
// valueChanged is of type Int?, not Int


if valueChanged == nil {
print("\(pi) conversion to Int doesn't maintain value")
}

Required Initializers

標示required 讓 subclass都必須實行這個init。有required就不必再寫override。

class SomeClass {
required init() {
// initializer implementation goes here
}
}

Setting Default property with functions and closures

class SomeClass {
let someProperty: SomeType = {
// create a default value for someProperty inside this closure
// someValue must be of the same type as SomeType
return someValue
}()
}

最後會有一個()結尾,這是告訴swift要馬上執行這個closure。沒有寫的話只是單純把closure assign給這個變數。

不能在closure裡用self的東西,因為這時候instance裡的其他部分都還沒初始化完成。

跟computed Property的差別

raw-image
  1. 寫法不同,computed property只能用var,後面也不需跟著()
  2. computed property每次叫到都會重新計算結果,stored property只會初始化一次。
留言
avatar-img
留言分享你的想法!
avatar-img
Michelle Chen的沙龍
8會員
34內容數
紀錄iOS開發上遇到的問題或是一些流程筆記。主要都是Swift。
Michelle Chen的沙龍的其他內容
2024/09/06
本文介紹了使用KeyboardLayoutGuide的方法,以及在不同iOS版本和設備上遇到的佈局問題。透過調整TextView的底部對齊方式,成功解決了在模擬器和真實設備上出現的錯誤,提供了有用的建議給開發者。本文還探討了為何在iOS15與Xib的組合使用中會出現問題,以及解決方案。
Thumbnail
2024/09/06
本文介紹了使用KeyboardLayoutGuide的方法,以及在不同iOS版本和設備上遇到的佈局問題。透過調整TextView的底部對齊方式,成功解決了在模擬器和真實設備上出現的錯誤,提供了有用的建議給開發者。本文還探討了為何在iOS15與Xib的組合使用中會出現問題,以及解決方案。
Thumbnail
2024/08/07
使用者回報的超級奇怪線上問題,用數字鍵盤(NumberPad)更改欄位時,送出後尾數都會消失。例如:30 ⭢ 3,52 ⭢ 5。 尋尋覓覓了兩天終於被我找到這篇,apple的奇葩的bug 重現條件 iOS17 手機設定是繁體中文語系 前一個用過的鍵盤是Cangjie倉頡 or Suchen
2024/08/07
使用者回報的超級奇怪線上問題,用數字鍵盤(NumberPad)更改欄位時,送出後尾數都會消失。例如:30 ⭢ 3,52 ⭢ 5。 尋尋覓覓了兩天終於被我找到這篇,apple的奇葩的bug 重現條件 iOS17 手機設定是繁體中文語系 前一個用過的鍵盤是Cangjie倉頡 or Suchen
看更多
你可能也想看
Thumbnail
在小小的租屋房間裡,透過蝦皮購物平臺採購各種黏土、模型、美甲材料等創作素材,打造專屬黏土小宇宙的療癒過程。文中分享多個蝦皮挖寶地圖,並推薦蝦皮分潤計畫。
Thumbnail
在小小的租屋房間裡,透過蝦皮購物平臺採購各種黏土、模型、美甲材料等創作素材,打造專屬黏土小宇宙的療癒過程。文中分享多個蝦皮挖寶地圖,並推薦蝦皮分潤計畫。
Thumbnail
小蝸和小豬因購物習慣不同常起衝突,直到發現蝦皮分潤計畫,讓小豬的購物愛好產生價值,也讓小蝸開始欣賞另一半的興趣。想增加收入或改善伴侶間的購物觀念差異?讓蝦皮分潤計畫成為你們的神隊友吧!
Thumbnail
小蝸和小豬因購物習慣不同常起衝突,直到發現蝦皮分潤計畫,讓小豬的購物愛好產生價值,也讓小蝸開始欣賞另一半的興趣。想增加收入或改善伴侶間的購物觀念差異?讓蝦皮分潤計畫成為你們的神隊友吧!
Thumbnail
Kotlin 中存取類別的屬性是一個重要的操作,透過 getter 與 setter 宣告方式讓我們可以使用 var 或 val 來宣告屬性。本篇文章介紹了在類別中宣告屬性的範例以及存取與修改屬性的操作。
Thumbnail
Kotlin 中存取類別的屬性是一個重要的操作,透過 getter 與 setter 宣告方式讓我們可以使用 var 或 val 來宣告屬性。本篇文章介紹了在類別中宣告屬性的範例以及存取與修改屬性的操作。
Thumbnail
Xcode15的 @escaping closure裡解包後的[weak self]不必再寫 self了!! 用一個範例class Test來實驗,裡面只有一個變數a跟一個testClosure回"test",再用callTestClosure把變數a改成"test" 編譯正常!變數a成功被改成
Thumbnail
Xcode15的 @escaping closure裡解包後的[weak self]不必再寫 self了!! 用一個範例class Test來實驗,裡面只有一個變數a跟一個testClosure回"test",再用callTestClosure把變數a改成"test" 編譯正常!變數a成功被改成
Thumbnail
swift讀書筆記 Documentation Edit descriptiondocs.swift.org objective-c 的init 會return value,swift 不會。 所有的property都必須在Init()裡面設定初始值,或設定stored property,這種
Thumbnail
swift讀書筆記 Documentation Edit descriptiondocs.swift.org objective-c 的init 會return value,swift 不會。 所有的property都必須在Init()裡面設定初始值,或設定stored property,這種
Thumbnail
Immutable interface 讓封裝更有彈性,不用擔心 setter 的過度開放。當不希望物件被不允許的對象修改時,只需讓對方取得 getter 的介面即可,反之,讓能夠允許修改的對象取得有 setter 的物件即可。
Thumbnail
Immutable interface 讓封裝更有彈性,不用擔心 setter 的過度開放。當不希望物件被不允許的對象修改時,只需讓對方取得 getter 的介面即可,反之,讓能夠允許修改的對象取得有 setter 的物件即可。
Thumbnail
最近工作上以及私下跟朋友討論時,剛好都遇到了 Null(不存在)類型的處理,通常我不會特別去在意這件事情,然而近年讀了一些關於 Null 的文章後(如:The worst mistake of computer science)對於這件事情的看法有不少改觀。
Thumbnail
最近工作上以及私下跟朋友討論時,剛好都遇到了 Null(不存在)類型的處理,通常我不會特別去在意這件事情,然而近年讀了一些關於 Null 的文章後(如:The worst mistake of computer science)對於這件事情的看法有不少改觀。
Thumbnail
Python是一種物件導向的程式語言,它讓我們可以使用類別(Class)來定義和創建物件,想像一個物件就像是一個實體,可以包含資料和功能。 舉例來說,一個人可以被視為一個物件,它有姓名、年齡等資料,還可以說話、走路等功能。類別就像是一個模板,它描述了物件的特徵和行為。 Python中,我們使用
Thumbnail
Python是一種物件導向的程式語言,它讓我們可以使用類別(Class)來定義和創建物件,想像一個物件就像是一個實體,可以包含資料和功能。 舉例來說,一個人可以被視為一個物件,它有姓名、年齡等資料,還可以說話、走路等功能。類別就像是一個模板,它描述了物件的特徵和行為。 Python中,我們使用
Thumbnail
在類別一節中,我們可以用Student類別的實體來存取類別中的name變數、score字典、以及其中的所有方法,這些可以被類別以外的程式碼所直接存取的屬性稱為公有屬性(public attribute)、可以被類別以外的程式碼所直接呼叫的方法稱為公有方法(public method)。
Thumbnail
在類別一節中,我們可以用Student類別的實體來存取類別中的name變數、score字典、以及其中的所有方法,這些可以被類別以外的程式碼所直接存取的屬性稱為公有屬性(public attribute)、可以被類別以外的程式碼所直接呼叫的方法稱為公有方法(public method)。
Thumbnail
賦值 (Assign Value) 想成套繩圈的動作, var 的繩圈是可以鬆綁重來的,val 套住對方就不能換了,而進階版 const val 綁住對方之後,對方的時間就被凍結了。 其實,以 Kotlin 的程式語言設計來說,比起賦值 (Assign Value),用賦址 (Assign
Thumbnail
賦值 (Assign Value) 想成套繩圈的動作, var 的繩圈是可以鬆綁重來的,val 套住對方就不能換了,而進階版 const val 綁住對方之後,對方的時間就被凍結了。 其實,以 Kotlin 的程式語言設計來說,比起賦值 (Assign Value),用賦址 (Assign
Thumbnail
行程 (Process),正如其名,指的是正在執行的程式 (Program),變數在其之中,是獲得命名,能保留自我的少數特殊存在。如果變數屬於全域變數 (Global Value),那麼其生命週期就會和行程一致,其他較短生命週期的都是局部變數 (Local Value)。 從一而終,在生命中止前不變
Thumbnail
行程 (Process),正如其名,指的是正在執行的程式 (Program),變數在其之中,是獲得命名,能保留自我的少數特殊存在。如果變數屬於全域變數 (Global Value),那麼其生命週期就會和行程一致,其他較短生命週期的都是局部變數 (Local Value)。 從一而終,在生命中止前不變
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News