Swift中的 @property Wrapper

屬性包裝器

屬性包裝器在管理屬性如何存儲和定義屬性的代碼之間添加了一個分隔層。舉例來說,如果你的屬性需要線程安全性檢查或者需要在數(shù)據(jù)庫中存儲它們的基本數(shù)據(jù),那么必須給每個屬性添加同樣的邏輯代碼。當(dāng)使用屬性包裝器時,你只需在定義屬性包裝器時編寫一次管理代碼,然后應(yīng)用到多個屬性上來進(jìn)行復(fù)用。
比如定義一個包裝器TestA,TestA確保其值在大于10的時候返回10,小于10的時候就返回對應(yīng)的值。
在Test A這個例子中,我們還定義了一個構(gòu)造方法,給num賦初始值。在使用的時候,我們可以通過@TestA(numValue: 5) var width: Int 這種方式給對應(yīng)的裝飾器賦值,這句話相當(dāng)于width的初始值為5。
我們還可以通過$符號來獲取裝飾器的一個呈現(xiàn)值。在TestA中projectedValue就是呈現(xiàn)值,通過range1.$width來訪問。

@propertyWrapper
struct TestA {
    var num: Int
    var projectedValue: Bool
    var wrappedValue: Int {
        get {
           return num
        }
        set {
            if newValue > 10 {
                num = 10
                projectedValue = true
            }else {
                num = newValue
            }
        }
    }
    
    init(numValue: Int) {
        num = numValue
        projectedValue = false
    }
}

現(xiàn)在定義一個類SCRange,它有屬性width和height,但是我們在使用了TestA這個裝飾器去修飾這2個屬性的時候,就相當(dāng)于規(guī)定了width和height的最大值就是10。

class SCRange {
    @TestA(numValue: 5) var width: Int
    @TestA(numValue: 5) var height: Int
}

func test1() {
        let range1: SCRange = SCRange()
        print(range1.width)
        range1.width = 50
        print(range1.width)
        print(range1.$width)
    }
// 結(jié)果打?。?
// 結(jié)果打?。?0
// 結(jié)果打印:true
綜合例子:

在下面這個例子,定義了一個線程安全的Int類型,在多線程的訪問中可以保證數(shù)據(jù)被安全的操作。我們定義了一個賣票的類Ticket和subTicket方法,總票數(shù)ticketNum是100張,同時有多個線程在賣票,這個時候我們就要保重多個線程對總票數(shù)的安全操作,不會多賣或少賣。

在ThreadSafeNum這個裝飾器中,我們定義了NSLock的鎖,對num的讀寫我們都加了鎖,保證數(shù)據(jù)讀寫多線程的安全。

@propertyWrapper
struct ThreadSafeNum {
    private var num: Int
    let myLock: NSLock = NSLock()
    var wrappedValue: Int {
        get {
            myLock.lock()
            defer {myLock.unlock()}
            return num
        }
        
        set {
            myLock.lock()
            defer {myLock.unlock()}
            num = newValue
        }
    }
    
    init(saftNum: Int) {
        num = saftNum
    }
}

class Ticket {
    @ThreadSafeNum(saftNum: 100) var ticketNum: Int
    
    func subTicket() {
        ticketNum = ticketNum - 1
        if ticketNum <= 0 {
            print("沒票了")
        }else {
            print("還剩\(ticketNum)")
        }
    }
}

func test2() {
        let ticket: Ticket = Ticket()
        for _ in 0...199 {
            DispatchQueue.global().async {
                ticket.subTicket()
            }
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 屬性 屬性將值與特定的類、結(jié)構(gòu)體或枚舉關(guān)聯(lián)。存儲屬性會將常量和變量存儲為實例的一部分,而計算屬性則是直接計算(而不...
    xiaofu666閱讀 533評論 0 0
  • 屬性 屬性將值與特定的類、結(jié)構(gòu)體或枚舉關(guān)聯(lián)。存儲屬性會將常量和變量存儲為實例的一部分,而計算屬性則是直接計算(而不...
    Upping8閱讀 247評論 0 0
  • 引言 繼續(xù)學(xué)習(xí)Swift文檔,從上一章節(jié):結(jié)構(gòu)體和類,我們學(xué)習(xí)了Swift結(jié)構(gòu)體和類相關(guān)的內(nèi)容,如結(jié)構(gòu)體和類的定義...
    shiyueZ閱讀 1,609評論 0 2
  • 在使用 Swift 開發(fā)的過程中,經(jīng)常會遇到諸如 SwiftUI 中的 @State,Combine 中的 @Pu...
    猴子的餅干閱讀 3,797評論 1 13
  • 存儲屬性 - Stored Properties 相當(dāng)于 OC 的下劃線成員變量 適用于:結(jié)構(gòu)體 、 類 類型:常...
    Sunday_David閱讀 409評論 0 0

友情鏈接更多精彩內(nèi)容