11 months ago

最近在學Swift4,打算用來開發iOS(雖然有點擔心iOS的市佔率下滑啊),覺得Swift這門語言蠻特別的,有些語法設計上十分精巧,在此筆記一些用法。

Optional Value

Optional Value:
在Swift中,我們可以顯式直接assign一個值給變數,但又可能遇到值不存在的情況,例如從網路獲取資料或從檔案夾讀取檔案,這可能發生有讀取到值或沒有讀取到的兩種狀況,如果不仔細處理的話可能會在 runtime時產生錯誤;
Swift針對變數值可能不存在的狀況提供Option Value的解法,將變數宣告為Optional value,並讓編譯器檢查去強迫使用安全拆封unwrapped變數的方式,減少runtime錯誤

// 宣告時在形態後加上 ?

var name: String? = "1213"

// 透過if else拆封 optional value,如果值為nil會自動到else

if let judge=name{
    print("value is \(judge)")
}else{
    print("name has no value")
}

// 可以透過guard拆封,類似於if,但是變數的scoped不同,guard必須搭配else做錯誤處理

// else中必須含有 return / throw 跳脫 guard主體的方式

// 但是 return 只能在 func中使用, throw 則要搭配 do..catch做處理

func unwrapValue(){
    guard let judge = name else {
        return
    }
    print("跟if不同之處,judge可以在guard宣告外使用, \(judge)")
}
unwrapValue()


// String?是不能直接assing給String的!,必須要 unwrapped

// var name2:String = name

// 可以用!快速unwrapped optional value,但可能會出錯喔

var name2:String = name!

Emumerations

Emumerations:
Enum用來將相關變數定義一塊,如紅綠燈的狀態有紅、黃、綠等,用來做狀態管理相當方便;
有趣的是在Swift中,Enum本身是也是種Class,也就是說可以定義自己的Methods、使用Extension、Protocol等物件相關的語法。

enum TrafficSignal{
    case red
    case yellow
    case green
    
    var canPass:Bool {
        switch self {
        case .red:
            return false
        case .yellow:
            return true
        case .green:
            return true
        }
    }
}

// 加入切換燈號的Methods

// 直接宣告在TrafficSignal也可以

extension TrafficSignal{
    mutating func changeSignal(){
        switch self{
        case .red:
            self = .green
        case .yellow:
            self = .red
        case .green:
            self = .yellow
        }
    }
}

// 宣告一個變數型態為Enum,並指定為其中一個狀態

var ts1: TrafficSignal = .red
var ts2 = TrafficSignal.red

ts1.canPass
ts1.changeSignal()
ts1.canPass

Class與Protocol

Protocol,也就是interface啦,個人非常喜歡interface的設計,因為用起來比繼承彈性,保留實踐的空間外,又提供型別與方法上的檢查避免低級 nil的致命錯誤,在這物件導向為主的世界有interface真的很不錯

protocol Movable {
    var x: Int { get set }
    var y: Int { get set }
    func move(x: Int, y: Int)
}

class Point: Movable {
    var x: Int = 0
    var y: Int = 0
    var connectedPoint: Point?
    
    init(x: Int, y: Int){
        self.x = x
        self.y = y
    }
    
    func connect(p: Point){
        self.connectedPoint = p
    }
    
    func move(x: Int, y: Int) {
        self.x = x
        self.y = y
    }
}

var p1: Point = Point(x:10, y:20)
var p2: Point = Point(x:10, y:20)


func isMovable(m: Movable){
    print("m should be movable")
}

isMovable(m: p1)

補充

  1. mutation:
    如果function要修改self值(通常是擴展基本屬性時會用上),需要定義mutation才可以,不然會編譯錯誤
  2. weak/unowned:
    牽涉到 Swift的記憶體管理,避免兩物件互相reference後產生殭屍的記憶體洩漏問題,詳細參考hugolu: 記憶體管理 ARC - Automatic Reference Counting
← Vue 插件開發 - 聊天視窗滾動與自動加載,關於MutationObserver/Custom Directive [從libuv/v8到nodejs 系列] :Libuv - 操作File System →
 
comments powered by Disqus