簡體   English   中英

設置兩個變量后如何調用方法

[英]How to call a method once two variables have been set

我正在使用 iOS Swift,並且我試圖了解在請求完成后設置兩個變量的值(非空值)后如何執行method

在閱讀了一些文檔之后,我發現了一些有趣的概念。 第一個是didSet ,它作為observer工作。

如果我只需要一個變量,我可以通過簡單地使用didSet來調用該方法

設置

var myVar: String  0 {
    didSet {
        print("Hello World.")

    }
}

不過,我還需要等待第二個myVar2 ,所以它不起作用。

我還找到了DispatchQueue ,我可以在調用該方法之前使用它等待一秒鍾(我正在使用的請求非常快)

調度隊列

 DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute:  {
            print("Hello world")
        })

但我認為這個解決方案效率不高。

無論如何將這兩個變量或請求組合起來,以便在完成設置值后調用方法?

更新我試圖復制大衛的答案,我認為這是正確的,但我在每個\.

在沒有更多上下文的情況下,表達式的類型是模棱兩可的

我在這里復制我當前的代碼

var propertiesSet: [KeyPath<SearchViewController, Car>:Bool] = [\SearchViewController.firstCar:false, \SearchViewController.secondCar:false] {
    didSet {
        if propertiesSet.allSatisfy({ $0.value }) {
            // Conditions passed, execute your custom logic
            print("All Set")
        } else {
            print("Not yet")
        }
    }
}

 var firstCar: Car? {
     didSet {
        propertiesSet[\SearchViewController.firstCar] = true
     }
 }

 var secondCar: Car?  {
     didSet {
        propertiesSet[\SearchViewController.secondCar] = true
     }
 }

變量是單獨設置的,每個變量都是根據自己的要求設置的。

您可以將屬性設為optional ,並在調用function之前檢查它們是否都設置了值。

var varA: String? = nil {
    didSet {
        if varA != nil && varB != nil {
            myFunc()
        }
    }
}

var varB: String? = nil {
    didSet {
        if varA != nil && varB != nil {
            myFunc()
        }
    }
}

或者,您可以在每個didSet上調用function並在function的開頭使用guard條件來檢查您的兩個屬性是否都有值,或者退出:

var varA: String? = nil {
    didSet {
        myFunc()
    }
}

var varB: String? = nil {
    didSet {
        myFunc()
    }
}

func myFunc() {
    guard varA != nil && varB != nil else { return }
    // your code
}

首先,您應該非常仔細地考慮您的語義在這里。 當您說“設置”時,您的意思是“分配了一個值”還是“分配了一個非零值”? (在這種情況下,我假設您的意思是后者。)您應該問自己,如果您的方法已經觸發,然后設置了另一個值,會發生什么? 如果其中一個屬性設置了一個值,然后設置了 nil,然后設置了另一個值,該怎么辦? 那應該觸發該方法 1、2 或 3 次嗎?

只要有可能,您應該通過要求將值設置在一起(例如在init而不是可變屬性中)來努力使這類問題變得不可能。

但顯然在某些情況下這是必要的(UI 是最常見的)。

如果您的目標是 iOS 13+,您應該探索結合這些類型的問題。 作為一種方法:

class Model: ObservableObject {

    @Published var first: String?
    @Published var second: String?
    @Published var ready = false

    private var observers: Set<AnyCancellable> = []

    init() {
        $first.combineLatest($second)
            .map { $0 != nil && $1 != nil }
            .assign(to: \.ready, on: self)
            .store(in: &observers)
    }
}

let model = Model()

var observers: Set<AnyCancellable> = []

model.$ready
    .sink { if $0 { print("GO!") } }
    .store(in: &observers)

model.first = "ready"
model.second = "set"
// prints "GO!"

另一種方法是將附帶的包含選項的 state 與您正在構建的實際 object 分開,但事實並非如此。

// Possible parameters for Thing
struct Parameters {
    var first: String?
    var second: String?
}

// The thing you're actually constructing that requires all the parameters
struct Thing {
    let first: String
    let second: String

    init?(parameters: Parameters) {
        guard let first = parameters.first,
            let second = parameters.second
            else { return nil }
        self.first = first
        self.second = second
    }
}

class TheUIElement {
    // Any time the parameters change, try to make a Thing
    var parameters: Parameters = Parameters() {
        didSet {
            thing = Thing(parameters: parameters)
        }
    }

    // If you can make a Thing, then Go!
    var thing: Thing? {
        didSet {
            if thing != nil { print("GO!") }
        }
    }
}

let element = TheUIElement()
element.parameters.first = "x"
element.parameters.second = "y"
// Prints "GO!"

您需要為所有需要設置的變量添加一個didSet以使您的條件通過。 還要創建一個Dictionary ,其中包含需要設置的變量的KeyPath和一個表示它們是否已經設置的Bool

然后,您可以在Dictionary上創建一個didSet ,其中包含所需變量的“設置狀態”,當它們的所有值都為true時,意味着所有這些值都已設置,執行您的代碼。

由於使用Dictionary而不是手動編寫條件,例如if aSet && bSet && cSet ,該解決方案可以很好地擴展到任意數量的屬性,這很容易失控。

class AllSet {
    var propertiesSet: [KeyPath<AllSet, String>:Bool] = [\.myVar:false, \.myVar2:false] {
        didSet {
            if propertiesSet.allSatisfy({ $0.value }) {
                // Conditions passed, execute your custom logic
                print("All Set")
            } else {
                print("Not yet")
            }
        }
    }

    var myVar: String {
        didSet {
            propertiesSet[\.myVar] = true
        }
    }

    var myVar2: String {
        didSet {
            propertiesSet[\.myVar2] = true
        }
    }

    init(myVar: String, myVar2: String) {
        self.myVar = myVar
        self.myVar2 = myVar2
    }
}

let all = AllSet(myVar: "1", myVar2: "2")
all.myVar = "2" // prints "Not yet"
all.myVar2 = "1" // prints "All set"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM