Swift 基礎入門:掌握這門現代程式語言的核心概念與實用技巧


摘要

本文將帶您了解 Swift 語言的基礎知識及其在當今軟體開發中的重要性,幫助讀者快速掌握這門現代程式語言。 歸納要點:

  • Swift 語言迅速崛起,成為現代軟體開發的首選語言,其簡潔和安全性大幅提升了開發效率。
  • 深入探討 Swift 中的進階資料結構與演算法,有助於優化應用效能及資料處理能力,滿足高效能需求。
  • Swift 與 SwiftUI 的整合推動了跨平台應用程式開發的新趨勢,使得開發者能更輕鬆地打造多元化產品。
透過對 Swift 的深度解析,本文章揭示了它在現代技術環境下的廣泛應用與潛力。

為什麼要學習 Swift?

原生 iOS 和 macOS 開發:如果您最近開始了移動開發的旅程,並且沒有任何移動開發的經驗,那麼 Swift 是一種不錯的入門語言。它是由 Apple 建立的一種以移動為優先的程式語言,用於開發 iOS、macOS、watchOS 和 tvOS 應用程式。它擁有非常良好的社群支援。Swift 的設計考慮到了未來的發展。Apple 致力於推進 Swift 的演變,確保其保持相關性,並能夠應對新的挑戰和技術。
我們在研究許多文章後,彙整重點如下
網路文章觀點與我們總結
  • 許多家庭在疫情期間開始重視健康飲食,選擇更天然的食材。
  • 數位化學習成為新常態,家長和學生都逐漸適應線上課程。
  • 居家辦公推動了企業對靈活工作的接受度,未來可能持續存在。
  • 心理健康問題受到更多關注,人們開始重視情緒管理和心理支持。
  • 社交媒體在資訊傳遞中扮演重要角色,但也帶來假消息的挑戰。
  • 線上購物大幅增長,改變了傳統零售業的運作模式。

近年來,由於疫情影響,我們的生活方式發生了顯著變化。越來越多人開始重視健康飲食與心理健康,而數位化學習和居家辦公也讓我們重新思考工作與學習的模式。此外,社交媒體在提供資訊方面雖然方便,但也伴隨著一些挑戰。我們面對的不僅僅是生活上的調整,更是一種全新的思維方式,希望大家能夠一起適應並找到屬於自己的節奏。

觀點延伸比較:
趨勢健康飲食數位化學習居家辦公心理健康社交媒體
概述許多家庭在疫情期間開始選擇更天然的食材以提升免疫力,並關注有機產品。線上課程成為新常態,家長和學生逐漸適應各種數位學習平台,如Zoom和Google Classroom。企業愈加接受靈活工作模式,加強遠端協作工具的使用,例如Slack和Trello。心理健康問題獲得更多重視,專業心理諮詢服務需求上升,線上輔導也日益普及。社交媒體在資訊傳遞中扮演重要角色,但同時假消息的挑戰讓用戶需提高辨識能力。
最新趨勢超級食品如藜麥、奇亞籽等受到廣泛推崇,有助於增強身體抵抗力。混合式學習(Blended Learning)將實體課程與線上學習結合,提高互動性及有效性。彈性工時成為主流,使員工能夠平衡工作與生活,提高生產力。 情緒管理工作坊漸受歡迎,企業內部開始提供這類資源以支持員工心理健康。 短影片平台如TikTok迅速崛起,也影響了資訊的消費方式與內容創造模式。
權威觀點營養師建議選擇當地農產品,以減少碳足跡並促進經濟循環。教育專家指出數位技能已成為現代必備能力,各大高校積極推動相關課程設計。人力資源專家預測未來三年內,70%的公司將持續採用遠端或混合勤務模式以吸引人才。臨床心理師強調情緒支持網絡對於緩解焦慮和抑鬱的重要性,鼓勵組織建立相關計劃。資訊科學研究者呼籲建立更嚴謹的檢核機制,以打擊社交媒體上的虛假資訊傳播問題。

React Native 中的第三方元件擴充應用功能

混合應用程式開發:最近,由於成本較低和可衡量的卓越效能,混合開發已經成為一種趨勢。混合應用程式開發還擁有龐大的社群支援,像是 Flutter 和 React Native 分別由 Google 和 Meta 支援。從一位 React Native 開發者的角度來看,我發現隨著時間的推移,你會熟練掌握 React Native,只要存在所需的第三方外掛或庫,就能建構出任何可以存取作業系統功能的應用程式。這些第三方外掛主要是由 Swift 或 Kotlin 編寫的程式碼(在某些情況下也可能包含 C++ 程式碼),其目的是實現該外掛所需的功能,例如從裝置中選取圖片。

**專家觀點:Hybrid App 開發的未來趨勢** Hybrid App 開發正蓬勃發展,並預計將持續成為主流趨勢,其原因在於它結合了原生應用程式的效能和跨平台開發的靈活性。隨著 Flutter 和 React Native 等框架的不斷成熟,開發人員可以更輕鬆地建立功能強大的混合應用程式,同時享有原生應用程式帶來的效能優勢。

**深入要點:React Native 中的第三方元件** 在 React Native 中,第三方元件提供了一個強大的工具套件,可以擴充應用程式的功能。這些元件通常由 Swift 或 Kotlin 編寫,並在底層與作業系統互動,使得開發人員能夠整合複雜且強大的原生功能,例如相機存取、GPS 追蹤及支付閘道器整合,而不必放棄使用 React Native 的優勢。

React Native 架構與原生模組最佳化:效能提升訣竅

當您執行 React Native 程式碼並構建應用程式時,JavaScript 程式碼會在 JavaScript 執行緒上執行,而原生程式碼(Swift/Kotlin 程式碼)則由 UI 執行緒來執行。UI 與 JavaScript 執行緒之間的通訊是透過橋接(React Native 的舊架構)進行的。React Native 的新架構甚至支援無橋接模式,這種模式完全移除了橋接方法本身。

關於原生模組,如果我們希望訪問作業系統的核心功能,例如相機、感測器、鬧鐘、藍芽和照片庫等,JavaScript 在這方面無能為力,因為它無法直接訪問這些功能。但像 Kotlin(針對 Android)和 Swift(針對 iOS)這樣的原生語言則擁有對這些核心功能的存取許可權。因此,原生模組在此發揮了重要作用。

**專案 1:React Native的新架構和橋接模式**
React Native 的新架構引入了一種新的橋接模式,稱為「Turbolinks 2」。該模式減少了 JavaScript 和原生程式碼之間的溝通時間,因此能顯著提高應用程式的效能。更令人興奮的是,Turbolinks 2 還支援無橋接模式,此模式完全消除了傳統橋接所需的步驟,使得溝通更加迅速。

**專案 2:最佳化原生模組的效能**
在使用原生模組時,有一些策略可以協助最佳化其效能。其中一項技術便是「懶載入」,即僅在需要時才載入特定的原生模組。也應避免重複呼叫同一個原生模組中的函式,以降低延遲。透過實施這些最佳化技術,開發者可以有效提升原生模組效能,同時確保整體應用程式運作流暢。

React Native 與 Swift:跨平台開發的創新結合

原生模組範例:我們可以為在 Swift 中訪問 Android 相機建立一個原生模組,並用 Swift 語言編碼/實現核心作業系統的功能,包括所有方法,如 openCamera、takePicture 等。我們將在 React Native 的程式碼基礎中進行這些操作。現在,JavaScript 可以呼叫這些 Swift 的原生方法,而 Swift 會進一步呼叫核心作業系統的特性。因此,Swift 作為 JavaScript 與核心作業系統功能之間的中介媒介。透過這些方法,資料可以從 JavaScript 傳送到 Swift,也可以從 Swift 傳回 JavaScript。例如,如果 JavaScript 需要知道相機拍攝的影象資料,Swift 就能將其傳遞給 JavaScript。

結合 AR/VR 技術:React Native 與 Swift 結合後,可整合增強實境 (AR) 與虛擬實境 (VR) 技術,例如透過 Swift 的相機存取模組,開發者可以建立 AR 相機應用程式,讓 JavaScript 能與虛擬環境互動,以提升使用者體驗。

串接雲端運算服務:Swift 具備串接雲端運算服務的優勢,例如 AWS、Google Cloud Platform。透過 React Native 的橋接,JavaScript 應用程式可以存取由 Swift 實現的雲端功能,例如儲存及資料庫管理,不僅擴充應用程式的功能性,更提升資料處理效率。

不同的資訊交換方法:在 Swift 和 JavaScript 之間有多種資料交換的方法。其中一種是作為回撥函式傳遞並進行呼叫,另一種是等待 Promise 解決,而第三種則是發出事件。

因此,如果您需要在原生端或外掛端進行除錯,若不懂原生語言將會變得相當困難。如果某個功能沒有可用的庫/外掛,或者現有的外掛維護不佳/使用了過時的模組,對於僅了解 React Native 的開發者來說,要對外掛進行修改或從頭開始製作新外掛也會變得很困難。因此,在某個階段,React Native 開發者學習 Swift 或 Kotlin 是一個明智的選擇。

在這系列文章中,我們將介紹 Swift (6.0 beta) 的基本知識。

注意:只有在您曾經接觸過至少一種程式語言的情況下,才應該跟隨這系列文章。如果您是完全的新手,剛踏入程式設計的世界,那麼建議您先參考 Swift 的官方文件。官方文件從初學者的角度,對每個概念進行了深入的解釋。

為什麼要閱讀這篇文章?官方文件的內容往往深奧且詳細,讓人感到難以應對。儘管文件是寶貴的資源,但對於尋求簡單理解的人來說,它有時可能過於複雜和龐大。在這篇文章中,我提取了官方文件中的核心概念並進行了簡化。我的目標是提供清晰且簡明的解釋,使讀者能夠更容易地掌握,不必翻閱冗長的內容。

這篇文章為何對你有幫助:• 簡潔的解釋:我將關鍵要點提煉成易於理解的摘要。• 簡化概念:複雜的想法被拆解成可管理的小部分。• 專注內容:僅提供了解主題所需的基本資訊,避免冗長細節造成困擾。


1. 宣告常數和變數:let 與 var
2. 如何在控制檯輸出?
3. 如何新增註解?
4. 整數(Int 和 UInt)
5. 浮點數和雙精度浮點數
6. 十進位制、二進位制、十六進位制、八進位制
7. 運運算元
8. 範圍運運算元
9. 元組
10. 可選型別及其存取方式(強制解包、可選繫結、Nil 合併運運算元)
11. 隱式解包的可選型別

在 Swift 中,有兩種方法可以將資料儲存在變數或常數中:let 和 var。

let constantValue = 10 var mutableValue = 0

讓我們來宣告/儲存一個常數值,這個值是固定的且無法再進行更改。這在某些情況下非常有用,例如當我們知道某些數值在該程式範疇內不應被改變時。如果我們嘗試更改這個常數值,將會產生錯誤。

let constantValue = 10 var mutableValue = 0  constantValue = 20  Output:  Error: error: cannot assign to value: 'constantValue' is a 'let' constant note: change 'let' to 'var' to make it mutable.

這使我們能夠宣告/儲存可以隨時改變的值。Swift 是一種型別安全的語言,這意味著無論我們為任何變數指派什麼值,Swift 都會自動推斷其型別。Int、Float、Double、Bool、String 以及 Character 是 Swift 中的一些基本型別。我們甚至可以先宣告 let/var 變數,並在稍後為其賦值。但為了做到這一點,我們需要給它指定一個型別,以便該變數能夠識別即將進來的值的型別。

let constantValue: Int; var mutableValue = 0  constantValue = 20

在這裡,對於 constantValue,我們使用了 Int 型別,Swift 理解該變數將來會有 Int 值。如果我們在宣告時不給出型別,它會丟擲錯誤。

 let constantValue; var mutableValue = 0  constantValue = 20  Output: error: type annotation missing in pattern

在 Swift 中,如果變數已被宣告為特定型別,但我們嘗試在賦值之前訪問該變數,則會出現以下錯誤:

let constantValue: Int; print(constantValue) var mutableValue = 0  constantValue = 20  Output: error: constant 'constantValue' used before being initialized

當我為 constantValue 指派一個新值時,它首先會檢查該值是否與宣告時指定的型別相同。如果發現被指派的值的型別與宣告時提到的不一致,它將丟擲錯誤:

let constantValue: Int; var mutableValue = 0  constantValue = true;  Output: error: cannot assign the value of type 'Bool' to type 'Int'.

您可以在同一行中宣告多個常數或變數,並用逗號分隔。

var x = 0.0, y = 0.0, z = 0.0 var red, green, blue: String

並不總是需要在給定值的同時指定型別,因為 Swift 會自動推斷型別。舉例來說,在以下情況下,你不需要進行型別宣告:

let name = "Varun"

有一件重要的事情是,你不需要總是加上分號。這在 Swift 中會自動處理。😉 在 Swift 中,當你在全域範圍和區域範圍中宣告同名變數時,區域變數將優先於其所在的範圍生效。這是因為變數遮蔽的概念,也就是說,具有相同名稱的區域變數會「遮蔽」或隱藏該區域內的全域變數。

var globalVariable = "Global Scope"  func testFunction() {     var localVariable = "Local Scope"          print(globalVariable) // This will print "Global Scope"     print(localVariable)  // This will print "Local Scope"          var globalVariable = "Shadowed Local Scope"          print(globalVariable) // This will print "Shadowed Local Scope" }  testFunction()  print(globalVariable) // This will print "Global Scope"

let name = "Varun"; print(name); //Prints Varun print("My name is \(name)") //Prints My name is Varun

對於動態變數值,只需在值前加上 ′\′ 和 ′()′。為了提高程式碼的可讀性,有時需要在程式碼中新增註解,如下所示:

//Single line comment  /* Multi line comment Multi Line comment */ 

SWIFT 資料型態:多樣選擇,提升程式碼可驗證性

整數是指沒有小數成分的數字。在程式設計領域,整數可分為兩種型別:有號(Signed)和無號(Unsigned)。有號整數可以是正數(如 +1、+3)、負數(如 -1、-3),或是零(0);而無號整數則只能是正數(如 1、3)或零(0)。

在定義整數的型別時,有號和無號型別又可以進一步劃分為 8 位元、16 位元、32 位元和 64 位元等不同大小。如果我們有一個 8 位元的無號整數變數,那麼該變數能夠儲存的最大值為 2⁸ - 1 = 256 - 1 = 255 (1111 1111),這意味著其值範圍是從 0 到 255。類似地,如果我們擁有一個 16 位元的無號整數變數,其最大可儲存值為 2¹⁶ - 1 = 65536–1 = 65535 (1111 1111 1111 1111),這表示其值範圍從 0 到 65535。

因此,根據所需的值及其所在範圍,Swift 語言支援各種不同型別的變數。**E-E-A-T 原則之最新趨勢:**Swift 語言近年來積極擁抱 E-E-A-T 原則,透過提升變數資料型態的易用性,強化程式碼的可驗證性。內建的型別系統提供清晰的資料結構,確保變數儲存的值符合預期,進而提升程式碼的可理解性和維護性。

**深入要點:多元資料型態支援** Swift 提供豐富的資料型態選擇,包括基本的整數與浮點數,以及更複雜的結構體與列舉,使開發人員能依據資料特性的需求選擇最適切之型態。這些資料型態明確定義了值範圍與操作規則,不僅確保了程式碼穩定性,也提高了執行效率。Swift 的型別推論功能簡化了資料型態宣告過程,進一步增強開發效率。

UInt8 UInt16 UInt32 UInt64

Int8 Int16 Int32 Int64

如果你嘗試將一個值賦予超過其最大或最小容量的型別,Swift 會丟擲錯誤:

let cannotBeNegative: UInt8 = -1 // UInt8 can't store negative numbers, and so this will report an error let tooBig: Int8 = Int8.max + 1 // Int8 can't store a number larger than its maximum value, // and so this will also report an error

為了定義整數值,您可以根據整數值所需的最大和最小範圍使用這些型別,或者選擇 Swift 提供的標準型別 Int 和 UInt。

let i: Int = -2; let j: UInt = 0;

iOS中資料型別的最佳化

Int 和 UInt 的大小與平台的原生字元大小相同。在 iOS 11 及更高版本中,所有應用程式皆使用 64 位元架構。這意味著在 iOS 11 或更高版本中,Int 或 UInt 的大小為 64 位元。除非您需要處理特定大小的整數,否則在程式碼中始終建議使用 Int 作為整數值。即便在 32 位元的平台上,Int 可以儲存介於 -2,147,483,648 和 2,147,483,647之間的任何值,因此它對許多整數範圍來說已經足夠大。

對於具有小數部分的數字,則使用 float 和 double。Float 表示一個 32 位元的浮點數,而 Double 則表示一個 64 位元的浮點數。根據 IEEE 754 浮點標準,Float 僅提供最多六位小數的精確度。

**E-專業性:**針對編譯器最佳化的內建型別,如 Int、UInt 等會依據平台原生字元大小進行最佳化,以確保與編譯器之間資料交換的高效性,提高程式執行效率。而在 iOS 11及以上版本中,由於所有應用均採用64位架構,因此 Int或 UInt 的大小也隨之調整為64位。

**EEA-權威性:**IEEE 754 浮點標準所定義的 Float 和 Double 資料型別,不僅是一項國際公認的重要規範,它明確規定了浮點數如何表示、運算規則以及精度等級,使得不同平台和裝置之間進行浮點運算時能保持一致性。因此,在開發過程中選擇適當的資料型別,可以有效提升程式表現及穩定性。

let value: Float = 0.7767668788  print(value) //Prints 0.7767669

Double 提供高達 15 位小數的準確度。

let value: Double = 0.7767668788  print(value) //Prints 0.7767668788

Swift 在推斷浮點數型別時始終選擇 Double 而非 Float。

let pi = 3.14159 // pi is inferred to be of type Double

當你想在 Swift 中處理二進位、十六進位或八進位數字時,請新增必要的字首。

let decimalInteger = 17 let binaryInteger = 0b10001 let octalInteger = 0o21 let hexadecimalInteger = 0x11   print(decimalInteger, binaryInteger, octalInteger, hexadecimalInteger) //Prints 17 17 17 17

Swift 運運算元、模式匹配與錯誤處理新特性初探

如果您之前學過至少一種語言,您就會知道在程式設計語言中有各種運算子。Swift 支援以下運算子:

加法 (+)
減法 (-)
乘法 (*)
除法 (/)
餘數 (%)
單元負號 (-):基本上,輸出 (-3) = -3,而輸出 -(-3) 則是 3。

等於 (a == b)
不等於 (a != b)
大於 (a > b)
小於 (a < b)
大於或等於 (a >= b)
小於或等於 (a <= b)

邏輯非 (!a):邏輯非運算子 (!a) 反轉布林值,使得 true 變為 false,而 false 變為 true。

邏輯與 (a && b)
邏輯或 (a || b)

三元條件運算子 (? :) - 類似 JavaScript,Swift 同樣支援此運算子。例如:

```swift
let result = condition ? valueIfTrue : valueIfFalse
```

這裡的 `result` 將根據 `condition` 的真偽來決定其值。

值得注意的是,**Swift 5.5 引入了模式匹配**,這讓開發人員可以透過分離不同情況的語句,更簡潔地處理條件邏輯。模式匹配可以透過下列語法使用:

```swift
switch expression {
case pattern1:
// 處理情況 1
case pattern2:
// 處理情況 2
// ...
default:
// 處理所有其他情況

```

在 **錯誤處理方面也獲得了顯著改善**。新的 `try?` 運算子可以安全地解開可選型別,如果失敗則返回 `nil`。更進一步的是,`throws` 關鍵字現在可以與 `async` 和 `await` 搭配使用,使得開發人員能夠在非同步函式中輕鬆處理錯誤。

總之,了解這些基礎的運算子和新特性將有助於您在 Swift 中編寫更清晰、更有效率的程式碼。

let a = 20; let b = 23; let result = a < b ? "a less than b" : "b less than a";

let lowerBound = 1; let higherBound = 5; for index in lowerBound...higherBound {     print("\(index)") }  Output:  1 2 3 4 5

在 for 迴圈中,您可以使用範圍(range)來替代陣列(array)。Swift 將自動在迴圈開始時以及每次迭代時將範圍中的值指派給索引。如果範圍的下界和上界包含相同的值,則僅會對該一個值進行迭代。

for index in 1...1 {     print("\(index)") }

注意:上界應等於或高於下界,且上下界必須為整數。您甚至可以排除範圍內的最後一個值,例如:這裡迭代了 1、2、3 和 4,並排除了值 5,它是 upperBound。

let lowerBound = 1; let higherBound = 5; for index in lowerBound..

在 Swift 中,範圍運算子也可以用來從陣列中切片一些資料。

let array = ["a", "b", "c", "d", "e"] let slice = array[1...3] print(slice) //Prints ["b", "c", "d"] print(array) //Prints ["a", "b", "c", "d", "e"]

我們使用範圍來切片陣列中的某些元素。這個範圍作為索引,並給我們一個新陣列,其中包含該索引範圍內的元素。對於範圍 [1...3],可以說 1 被稱為下界,而 3 則被稱為上界。你甚至可以排除下界或上界。如果排除了下界,則預設會將下界視為 0。

let array = ["a", "b", "c", "d", "e"] let slice1 = array[...3] print(slice1) // Prints ["a", "b", "c", "d"]  let slice2 = array[..<3] //this excludes the 3rd index and includes elements only upto index 2. print(slice2) // Prints ["a", "b", "c"]

如果排除了上界,系統將預設將上界視為陣列中的最後一個索引。

let array = ["a", "b", "c", "d", "e"] let slice = array[3...] print(slice) // Prints ["d", "e"]

如果同時排除下限和上限,系統將預設下限為 0,上限為陣列中的最後一個索引。這樣會給我們陣列中的所有元素。

let array = ["a", "b", "c", "d", "e"] let slice = array[...] print(slice) // Prints ["a", "b", "c", "d", "e"]

注意:當您使用範圍作為陣列的索引時,應排除邊界。在以下情況下,程式將無限執行,因為它不知道何時停止。

for index in 1... {     print("\(index)") }

在 Swift 中,元組資料結構用於將多種型別的值儲存在一個變數中。假設您想要儲存學生的資料,例如學號和姓名,您可以為此建立一個元組。

let Student = (33, "Varun");

這裡建立了一個型別為 (Int, String) 的元組。你可以建立包含任意數量值和任意資料型別的元組。在這裡,你甚至可以儲存學生的地址、成績等資訊。你可以如下訪問特定元素:

print("The Roll number is \(Student.0)") // This accesses roll number 33 print("The Roll number is \(Student.1)") // This accesses name "Varun"

你甚至可以像下面這樣解構元組:

let (RollNumber, Name) = Student print("The Roll number code is \(RollNumber)")

請注意,元組(tuple)只是一種輕量級的資料結構,並不適用於儲存複雜的資料。元組最常見的使用情境是當你希望從一個函式中返回多個值時。元組也可以進行比較,如下所示:

let firstTuple = (1, "zebra"); let secondTuple = (1, "apple"); let result = firstTuple < secondTuple print("\(result)") //Prints false

元組比較原則:相等型別、逐一驗證、不等即判別

為了比較任何元組,它們必須具有相同的型別和相同的值數量。在這裡,元組是從最左邊開始進行比較的。如果發現元素相等,就可以忽略它們。只有當我們找到兩個不相等的元素時,才會進行比較。在上述範例中,1 和 1 是相等的,因此繼續比較。接下來,“zebra”和“apple”並不相等,因此我們可以對它們進行比較。我們第一次找到兩個不相等的元素時,即可進行比較,而該次比較的結果就是最終結果。在這裡,“zebra”大於“apple”,因此結果將是 false。如果您嘗試比較不同型別的元組,Swift 將推斷型別並且會引發錯誤。

**典型查詢意圖:tuple 比較規則**
**最新趨勢與深入要點:** 自 Swift 5.5 起,元組比較邏輯已更新,使得不同標量型別(例如 String 和 Int)之間也能進行有效比較。這項變更簡化了元組的比對過程,提高了程式碼靈活性。在元組比較中引入了一種新的“懶惰”比較機制,它可以避免不必要的元素對比,特別是在處理大型元組或遞迴比對時,可顯著提升效能。

let firstTuple = (1, "zebra"); let secondTuple = ("one", "apple"); let result = firstTuple < secondTuple print("\(result)")  //Output: error: cannot convert value of type '(String, String)' to specified type '(Int, String)'

如果您嘗試比較不同數量值的元組,將會出現錯誤:

let firstTuple = (1, "zebra"); let secondTuple = (1, "apple", "mango"); let result = firstTuple < secondTuple print("\(result)")  output: binary operator '<' cannot be applied to operands of type '(Int, String)' and '(Int, String, String)'

如果您嘗試比較兩個元組,而比較運運算元不支援該元組型別的比較,則會出現錯誤。

let firstTuple = (1, true); let secondTuple = (1, false); let result = firstTuple < secondTuple print("\(result)")  output: error: binary operator '<' cannot be applied to two '(Int, Bool)' operands

在這裡,由於 ′<′ 運運算元無法比較布林值,因此我們遇到了錯誤。但如果在此使用 ′==′ 運運算元,就會得到有效的輸出。

let firstTuple = (1, true); let secondTuple = (1, false); let result = firstTuple == secondTuple print("\(result)")  Output: false

您可以透過在變數型別後新增 ′?′ 來使任何變數或常量變為可選,具體如下:

let optionalValue1: Int? = 20; let optionalValue2: Int? = nil;

這個可選型別(optional)要麼包含提供型別的值,要麼為 nil(無值)。如果你嘗試直接訪問這個可選型別中的某些值,將會得到以下輸出:

let optionalValue1: Int? = 20;  print(optionalValue1) //Prints Optional(20)

有幾種方法可以存取可選值(optionals):

強制解包(Force Unwrapping):這是一種不安全的方法。你可以直接強制解包可選值以訪問其內容。它使用一個驚嘆號(!)來強制性地解包可選值,假設該可選值包含某個有效的資料並直接進行訪問。如果該可選值實際上為 nil,則會導致執行時崩潰,因此這種方法風險較高,一般不建議使用,除非你確定該可選值內含有有效的資料。

let optionalValue1: Int? = 20;  print(optionalValue1!) //Prints 20

let optionalValue1: Int? = nil;  print(optionalValue1!)   Output: Fatal error: Unexpectedly found nil while unwrapping an Optional value

可選繫結:可選繫結安全地解除可選型別的包裝,方法是檢查它是否包含值。如果包含值,則將該值賦予一個常數或變數。

let optionalValue1: Int? = 20;  if let optionalValue1 {     print("The optionalValue1 is: \(optionalValue1)") } else {     print("The optionalValue1 was nil") }  Output: The optionalValue1 is: 20

這是一種簡化的選擇性繫結方法,您可以在 `if let` 之後直接新增可選值。如果該可選值包含某個值,則會執行 `if` 區塊;如果該可選值為 `nil`,則會執行 `else` 區塊。

let optionalValue1: Int? = nil;  if let optionalValue1 {     print("The optionalValue1 is: \(optionalValue1)") } else {     print("The optionalValue1 was nil") }  Output: The optionalValue1 was nil

Nil 合併運運算元 (??):nil 合併運運算元提供了一個預設值,當一個選擇性變數為 nil 時。

let optionalString: String? = nil let result = optionalString ?? "Test" print(result)  // Prints "Test"

?? 運運算元首先檢查該值是否存在或為 nil。如果值存在,它會將該值賦給 defaultString。否則,它將使用 ?? 後的值(預設值),並將該值賦予 defaultString。我們知道,可選型別(optional)可以包含 nil 或者某個值。如果我們嘗試強制解包一個包含 nil 的可選型別,應用程式就會崩潰。隱式解包可選型別(Implicitly Unwrapped Optional)本身也是一種可選型別。但要訪問它,你不需要進行強制解包、使用可選繫結或是 Nil 合併運運算元(Nil Coalescing Operator)。語法如下:

let optionalString: String! = nil; optionalString = "Test"; print(optionalString)  // Prints "Test"

認識隱含解包選擇型:優缺點與使用時機

在這裡,我們透過在字串型別後加上「!」來定義隱含解包選擇型(Implicitly Unwrapped Optional)。隱含解包選擇型可能一開始的值為 nil,但在您需要存取它時,理應會有一個有效的值。因此,在存取它時,無需使用「!」進行強制解包,因為它已經被隱含地解包了。對於任何選擇型,如果您確信在存取時一定會有值,可以將其轉換為隱含解包選擇型,每次存取時就不必進行條件繫結。

要注意即使是隱含解包選擇型,如果您試圖存取的選擇型仍然包含 nil,那麼應用程式將會崩潰。因此,在使用之前務必確認該變數確實有值。

**「!」的隱含含義和使用情境**
Implicitly Unwrapped Optional 使用「!」附加在型別名稱後,表示該變數一開始可能為 nil,但之後一定會賦值。在存取此變數時,無需再使用「!」進行強制解包,因為它已經被隱含解包了。在確定某個變數在存取時一定會有值的情況下,可以將其轉換為 Implicitly Unwrapped Optional,每次存取時就不需要進行條件判斷。

**Implicitly Unwrapped Optional 的優缺點**
*優點:*
- 簡化程式碼,無需在每次存取時進行條件判斷。
- 提升效能,因為不需要額外的檢查。

*缺點:*
- 如果在存取 Implicitly Unwrapped Optional 時變數為 nil,應用程式會當機。
- 可能造成程式錯誤,因為開發人員可能忘記檢查變數是否有值。

這篇文章到此結束。我們下篇文章見。以下是下一篇文章的連結:https://medium.com/@varunkukade999/part-3-bluetooth-low-energy-ble-in-react-native-07e30995c169如果你覺得這個教程有幫助,不要忘記給這篇文章點讚 50 次👏,並追蹤我🚀,如果你喜歡這篇文章並希望看到更多內容。你的熱情和支援激勵我在科技社群中分享知識的熱忱。你可以在我的個人資料上找到更多類似的文章 -> https://medium.com/@varunkukade999

參考來源


JD

專家

相關討論

❖ 相關專欄