[英]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.