使用 UIKIt + Combine + MVVM 進行 GUI 編程
課題
- 程序界面由3個文本編輯框和1個文本標簽組成。
- 要求文本標簽實時顯示3個文本編輯框所輸入的數字之和。
- 文本編輯框輸入的不是合法數字時,將其值視為0。
- 3個文本編輯框的初值分別為1,2,3。
創建工程
打開 Xcode,File / New / Project..
在 New Project 向導的第1頁,選 iOS / App
在向導的第2頁填上 Product Name: CombineExample
在向導的第3頁選擇任意文件夾點擊 Create 按鈕創建工程
關閉所創建的工程
添加 CombineCocoa 包
選中工程,在右鍵菜單中選 Add Packages... 打開 Apple Swift Packages 對話框
在搜索欄中輸入 https://github.com/CombineCommunity/CombineCocoa.git
回車開始搜索
選中搜索結果中的 CombineCocoa,點擊 Add Package 按鈕關閉對話框。
工程下方會出現 Package Dependencies,其中包含 CombineCocoa 0.4.0
ViewModel
在工程中添加 NumbersViewModel.swift 文件,內容如下:
import Foundation
import Combine
class NumbersViewModel: ObservableObject {
@Published
var number1 = "1"
@Published
var number2 = "2"
@Published
var number3 = "3"
@Published
var result = ""
init() {
$number1.combineLatest($number2, $number3)
.map { String((Int($0) ?? 0) + (Int($1) ?? 0) + (Int($2) ?? 0)) }
.assign(to: &$result)
}
}
配置 UI
打開 Main.storyboard 文件,在 View Controller Scene / View Controller / View 下面放置3個 Text Field 和1個 Label。
控件變量
打開 ViewController.swift 文件,在 ViewController 類中添加控件變量
@IBOutlet weak var tfNumber1: UITextField!
@IBOutlet weak var tfNumber2: UITextField!
@IBOutlet weak var tfNumber3: UITextField!
@IBOutlet weak var lblResult: UILabel!
使用 Assistant Editor 同時打開 Main.storyboard 文件,用 Control 鍵將控件變量掛到相應的控件上。
使用 MVVM 的解決方案
在 ViewController 類添加 NumbersViewModel 類的實例,并且在 viewDidLoad 方法中添加綁定控件的代碼
import UIKit
import Combine
import CombineCocoa
class ViewController: UIViewController {
// ...
var vm: NumbersViewModel!
var subscriptions = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
vm = NumbersViewModel()
vm.$number1.assign(to: \UITextField.text!, on: tfNumber1).store(in: &subscriptions)
vm.$number2.assign(to: \UITextField.text!, on: tfNumber2).store(in: &subscriptions)
vm.$number3.assign(to: \UITextField.text!, on: tfNumber3).store(in: &subscriptions)
vm.$result.assign(to: \UILabel.text!, on: lblResult).store(in: &subscriptions)
tfNumber1.textPublisher.compactMap{$0}.assign(to: &vm.$number1)
tfNumber2.textPublisher.compactMap{$0}.assign(to: &vm.$number2)
tfNumber3.textPublisher.compactMap{$0}.assign(to: &vm.$number3)
}
// ...
}
浙公網安備 33010602011771號