[英]Execute a method when a variable value changes in Swift
當變量值發生變化時,我需要執行一個函數。
我有一個單例類,其中包含一個名為labelChange
的共享變量。 此變量的值取自另一個名為Model
類。 我有兩個 VC 類,其中一個有一個按鈕和一個標簽,第二個只有一個按鈕。
當按下第一個 VC 類中的按鈕時,我正在使用此功能更新標簽:
func updateLabel(){
self.label.text = SharingManager.sharedInstance.labelChange
}
但是每當labelChange
的值發生更改時,我都想調用相同的方法。 因此,在單擊按鈕時,我只會更新labelChange
值,當發生這種情況時,我想用labelChange
的新值更新標簽。 同樣在第二個 VC 中,我能夠更新labelChange
值,但在更改此值時我無法更新標簽。
也許屬性是解決方案,但任何人都可以告訴我如何這樣做。
第二次修改:
單例類:
class SharingManager {
func updateLabel() {
println(labelChange)
ViewController().label.text = SharingManager.sharedInstance.labelChange
}
var labelChange: String = Model().callElements() {
willSet {
updateLabel()
}
}
static let sharedInstance = SharingManager()
}
第一個VC:
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
@IBAction func Button(sender: UIButton) {
SViewController().updateMessageAndDismiss()
}
}
第二個VC:
func updateMessageAndDismiss() {
SharingManager.sharedInstance.labelChange = modelFromS.callElements()
self.dismissViewControllerAnimated(true, completion: nil)
}
@IBAction func b2(sender: UIButton) {
updateMessageAndDismiss()
}
我做了一些改進,但我需要引用單例中第一個 VC 類的標簽。 因此,我將在單例中更新 VC 的標簽。
當我打印labelChange
的值時,該值正在更新並且一切正常。 但是當我嘗試從單例更新標簽上的值時,我收到一個錯誤:
在解開 Optional 值時意外發現 nil
並且錯誤指向單例類的第 4 行。
您可以簡單地對變量labelChange
使用屬性觀察labelChange
,並調用您想在didSet
調用的函數(或者willSet
如果您想在設置之前調用它):
class SharingManager {
var labelChange: String = Model().callElements() {
didSet {
updateLabel()
}
}
static let sharedInstance = SharingManager()
}
這在Property Observers 中有解釋。
我不確定為什么這在您嘗試時不起作用,但是如果您因為嘗試調用的函數( updateLabel
)在不同的類中而遇到問題,您可以在SharingManager
類中添加一個變量來存儲調用didSet
時要調用的函數,在這種情況下,您可以將其設置為updateLabel
。
編輯:
因此,如果您想從 ViewController 編輯標簽,您需要在 ViewController 類中使用 updateLabel() 函數來更新標簽,但將該函數存儲在單例類中,以便它知道要調用哪個函數:
class SharingManager {
static let sharedInstance = SharingManager()
var updateLabel: (() -> Void)?
var labelChange: String = Model().callElements() {
didSet {
updateLabel?()
}
}
}
然后將它設置在您擁有要調用的函數的任何類中,例如(假設 updateLabel 是您要調用的函數):
SharingManager.sharedInstance.updateLabel = updateLabel
當然,您需要確保負責該函數的視圖控制器仍然存在,以便單例類可以調用該函數。
如果您需要根據可見的視圖控制器調用不同的函數,您可能需要考慮鍵值觀察以在某些變量的值發生變化時獲得通知。
此外,您永遠不想像那樣初始化視圖控制器,然后立即設置視圖控制器的 IBOutlets,因為 IBOutlets 在其視圖實際加載之前不會被初始化。 您需要以某種方式使用現有的視圖控制器對象。
希望這可以幫助。
label.observe(\.text, changeHandler: { (label, change) in
// text has changed
})
基本上就是這樣,但有一點問題。 “observe” 返回一個你需要持有的 NSKeyValueObservation 對象! - 解除分配后,您將不再收到通知。 為了避免這種情況,我們可以將其分配給將保留的屬性。
var observer:NSKeyValueObservation?
// then assign the return value of "observe" to it
observer = label.observe(\.text, changeHandler: { (label, change) in
// text has changed,
})
您還可以觀察該值是否已更改或已首次設置
observer = label.observe(\.text, changeHandler: { (label, change) in
// just check for the old value in "change" is not Nil
if let oldValue = change.oldValue {
print("\(label.text) has changed from \(oldValue) to \(label.text)")
} else {
print("\(label.text) is now set")
}
})
有關更多信息,請在此處查閱 Apples 文檔
Apple 提供這些屬性聲明類型:-
1. 計算屬性:-
除了存儲的屬性之外,類、結構和枚舉還可以定義計算屬性,這些屬性實際上並不存儲值。 相反,它們提供了一個 getter 和一個可選的 setter 來間接檢索和設置其他屬性和值。
var otherBool:Bool = false
public var enable:Bool {
get{
print("i can do editional work when setter set value ")
return self.enable
}
set(newValue){
print("i can do editional work when setter set value ")
self.otherBool = newValue
}
}
2. 只讀計算屬性:-
具有 getter 但沒有 setter 的計算屬性稱為只讀計算屬性。 只讀計算屬性總是返回一個值,可以通過點語法訪問,但不能設置為不同的值。
var volume: Double {
return volume
}
3. 物業觀察員:-
您可以選擇在屬性上定義這些觀察者中的一個或兩個:
willSet在值被存儲之前被調用。
didSet在存儲新值后立即調用。
public var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
注意:-有關更多信息,請訪問專業鏈接https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html
還有另一種方法,通過使用 RxSwift:
將 RxSwift 和 RxCocoa Pod 添加到您的項目中
修改您的SharingManager
:
import RxSwift class SharingManager { static let sharedInstance = SharingManager() private let _labelUpdate = PublishSubject<String>() let onUpdateLabel: Observable<String>? // any object can subscribe to text change using this observable // call this method whenever you need to change text func triggerLabelUpdate(newValue: String) { _labelUpdate.onNext(newValue) } init() { onUpdateLabel = _labelUpdate.shareReplay(1) } }
在您的 ViewController 中,您可以通過兩種方式訂閱值更新:
一種。 訂閱更新,並手動更改標簽文本
// add this ivar somewhere in ViewController let disposeBag = DisposeBag() // put this somewhere in viewDidLoad SharingManager.sharedInstance.onUpdateLabel? .observeOn(MainScheduler.instance) // make sure we're on main thread .subscribeNext { [weak self] newValue in // do whatever you need with this string here, like: // self?.myLabel.text = newValue } .addDisposableTo(disposeBag) // for resource management
灣將更新直接綁定到 UILabel
// add this ivar somewhere in ViewController let disposeBag = DisposeBag() // put this somewhere in viewDidLoad SharingManager.sharedInstance.onUpdateLabel? .distinctUntilChanged() // only if value has been changed since previous value .observeOn(MainScheduler.instance) // do in main thread .bindTo(myLabel.rx_text) // will setText: for that label when value changed .addDisposableTo(disposeBag) // for resource management
並且不要忘記在 ViewController 中import RxCocoa
。
觸發事件只需調用
SharingManager.sharedInstance.triggerLabelUpdate("whatever string here")
在這里你可以找到示例項目。 只需執行pod update
並運行工作區文件即可。
var item = "initial value" {
didSet { //called when item changes
print("changed")
}
willSet {
print("about to change")
}
}
item = "p"
override var isHighlighted: Bool {
get { super.isHighlighted }
set {
super.isHighlighted = newValue
if newValue {
label.textColor = highlightedTextColor
contentView.backgroundColor = highlightedBackgroundColor
} else {
label.textColor = normalTextColor
contentView.backgroundColor = normalBackgroundColor
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.