前言
會研究綁定,主要是因為在研究 NSOutlineView (樹狀圖) 時,得知資料有二種處理方法,一種是由程式處理,一種是設定綁定,因為綁定的部份看不懂,所以才先研究簡單的綁定功能。
在網路上找到了這篇文章,看起來寫的蠻清楚的,例子也簡單好懂,不過實作時,偏偏無法運作,花了一晚找不到原因,也查不到相關資料,最後總算在某一篇問答中找到一句話,突破了盲點,才完成初步的綁定測試。
我的環境是:
macOS 10.15 Catalina
Xcode 11.1
Swift 5
也許之前的版本就沒有問題,這點我無法確定,底下一一說明操作經過。
基本設定
我就抄襲該篇的實作,先設計一個 Person 類別,繼承 NSObject,類別中有一個 scroe 屬性。並在 ViewController 中宣告 son 物件。
我原本以為是不是 scroe 不能宣告變數的類型?後來我有指定是 Int 也沒有問題,是我多慮了。
Storyboard 則放二個元件,一個 Slider 和一個輸入欄位。
綁定
-
選取 Slider
-
選取 Bindings Inspector
-
選取 Value
-
勾選 Bind to ,選擇 View Controller
-
選取 Model key Path,填入 son.score
同樣,輸入欄位也是同樣的綁定。
失敗的測試
就如一開始所說的,測試起來就是一片黑,完全沒有畫面,有如下的錯誤訊息。
這個過程卡了很久,Google 不少資料,但許多都是複雜的技術文章,寫的說明落落長,不然就是介紹 KVC、KVO、MVVM...等我還沒搞懂的一堆術語,愈看是頭愈大。
成功的測試
最後是 google 到一篇問答,有一個人提出一個關鍵詞 @objc,經過我各種測試之後,總算有了初步的成果。
於是我把程式改成如下,Person 類別中的 score 要加上 @objc,宣告 son 也要加上 @objc,這二個地方都要加,缺一不可。
再次執行果然就可以順利同步了。
【後記】後來又看有這種用法:
@objcMembers class Person: NSObject {
var score = 0
}
大概是表示內部屬性不用一一加 @objc 了。
文中有提到,在拉動 Slider 時,輸入欄位並不會立刻更新,而是等到 Slider 拉到定位,輸入欄位才會更新。如果要即時更新,可將 Slider 的 Continuous 屬性勾選即可。
文中也提到,Swift 中預設是關閉了 KVO 的屬性監聽,只要在 score 屬性前面添加一個關鍵字 dynamic 就可以開啟了。
經實際測試,若沒有加 dynamic,雖然將 son.score 設定初值,呈現時也沒有反應出來。
如下圖,雖然有設定 son.score = 10,一開始的畫面依然是 0。
我增加一個按鈕,按下去會將 son.scroe 設定為 50,但實測結果並不會影響畫面的元件。我經由 Debug 去看,son.score 的確有更新,程式並沒有錯誤。
後來把 dynamic 加入之後,初值與執行時去改變 son.score,畫面的元件果然都能順利同步了。
下圖是加上 synamic 的宣告,執行時初值就是 10 了。
增加的按鈕,按下去 Slider 和輸入欄位也都立刻變成 50。
額外的測試
我有試著把 Person 類別的 NSObject 繼承移除,結果在 son 前面加上 @objc 就會出錯,因此若要使用物件來綁定,NSObject 還是要繼承才行。
後來在我 ViewController 加了一個變數
@objc synamic var xyz = 0
我發現元件與此變數一樣可以綁定,綁定時就把 son.score 換成 xyz 即可。因此似乎也不一定要使用繼續 NSObject 的物件來綁定。細節我還不清楚,這只是實際測試結果。
除了數據,不少屬性也都可以綁定,例如我也把 Hidden 與 Enabled 綁定,結果當綁定數據為 0 時,元件就會消失或 Disabled,符合我們的預期。
綁定 NSUserDefaultsController
還有一種綁定 User Defaults Controller 的方法,使用起來比上面更簡單,程式都不用寫,可以直接綁定元件的各種屬性。
以底下為例,先選擇 Slider,將它的 Value 綁定 User Defaults Controller,Controller Key 選 values,Model Key Path 隨意命名,我用 abc,感覺就是把 Slider 的值與 abc 這個變數綁定。
同樣,輸入欄位把 Value 綁定到 abc。
底下是把 Button 的 Font Size 綁定到 abc。
執行時,拉動 Slider,果然除了輸入欄位的數字會同步變更,Button 的文字大小也同時跟著改變。
這個方式還有個特別的地方,就是當程式關閉後,再次開啟時,Slider 的位置與輸入欄位數字依然保持不變,似乎這個 abc 變數會記錄在某個地方,程式再次開啟時會保持在上次結束的狀態,不用自己寫程式去記錄,算是蠻不錯的特性。
- 瀏覽次數:8549
發表新回應