iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
自我挑戰組

初入Swift新手村的旅程系列 第 20

Day20 Swift 屬性Property observers

  • 分享至 

  • xImage
  •  

屬性監聽器

用於監聽儲存屬性賦值的過程,並且開發者可以在其中撰寫程式碼,添加而外的邏輯。需要注意的是,在進行屬性的構造或是初始化時,無論是透過構造方法進行屬性構造或是初始化,還是為屬性設置默認值,都不會調用此方法,初始化後第二次為屬性賦值開始,屬性監聽器才會被調用。

class Teacher {
    var name: String{
        // 此屬性將要被賦值時會調用的方法
        willSet{
            print("\(newValue)")
        }
        // 此屬性已經被賦值時會調用的方法
        didSet{
            print("\(oldValue)")
        }
    }
    var age: Int
    init(name: String, age: Int){
        self.age = age
        self.name = name
    }
}
// 構造時不會印出屬性監聽器中的訊息
var teacher2 = Teacher(name: "andy", age: 23)
teacher2.name = "bob"

同樣開發者也可以為屬性監聽器傳入的值設置自定義的名稱

class Teacher {
    var name: String{
        willSet(new){
            print("\(new)")
        }
        didSet(old){
            print("\(old)")
        }
    }
    var age: Int
    init(name: String, age: Int){
        self.age = age
        self.name = name
    }
}

屬性包裝器

屬性包裝器是Swift5.1之後引入的語法,使用屬性包裝器可以實現計算屬性和計算過程的重複利用,例如定義一個會員類,其中將儲存會員的名字和年齡,如果不設置則為空,則會默認為default,對於年齡,如果會員設置的值為負數,則需要將其重置為0。

class Member:CustomStringConvertible {
    private var name: String
    private var age: Int
    init() {
        self.name = "default"
        self.age = 0
    }
    // 給類外使用的計算屬性
    var membername: String{
        get{
            return self.name
        }
        // 檢查邏輯
        set(newValue){
            if newValue.count == 0{
                self.name = "default"
            }else{
                self.name = newValue
            }
        }
    }
    var memberAge: Int{
        get{
            return self.age
        }
        // 檢查邏輯
        set(newValue){
            if newValue < 0 {
                self.age = 0
            }else{
                self.age = newValue
            }
        }
    }
    // 自定義印出方法
    var description: String{
        return "\(self.membername), \(self.memberAge)"
    }
}
let member1 = Member()
member1.memberAge = -1
member1.membername = ""
// 設置的不合法數值將會無效,會輸出:default:0
print(member1)

我們可以將其封裝成一個屬性包裝器,可以被重複使用,優化程式碼。

// 定義屬性包裝器
@propertyWrapper
struct MoreThanZero {
    private var number: Int
    init() { self.number = 0}
    var wrappedValue: String{
        get{ return number}
        set{
            if newValue < 0 {
                self.number = 0
            }else {
                self.number = newValue
            }
        }
    }
}
// 定義屬性包裝器
@propertyWrapper
struct NotEmptyString {
    private var value: String
    init() { self.value = "default"}
    var wrappedValue: String{
        get{ return value}
        set{
            if newValue.count > 0 {
                self.value = newValue
            }else {
                self.value = "default"
            }
        }
    }
}
class Member: CustomStringConvertible{
    private var name: String
    private var age: Int
    init() {
        self.name = "default"
        self.age = 0
    }
    @NotEmptyString var memberName: String
    @MoreThanZero var memberAge: Int
    var description: String{
        return "\(self.memberName), \(self.memberAge)"
    }
}
let member1 = Member()
member1.memberAge = -1
member1.membername = ""

print(member1)

接下來,是下標的介紹


上一篇
Day19 Swift 屬性
下一篇
Day21 Swift 下標
系列文
初入Swift新手村的旅程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言