zwvista

导航

使用 SwiftUI + Combine + MVVM 进行 GUI 编程

课题

  1. 程序界面由3个文本编辑框和1个文本标签组成。
  2. 要求文本标签实时显示3个文本编辑框所输入的数字之和。
  3. 文本编辑框输入的不是合法数字时,将其值视为0。
  4. 3个文本编辑框的初值分别为1,2,3。

创建工程

打开 Xcode,File / New / Project..
在 New Project 向导的第1页,选 iOS / App
在向导的第2页的填上 Product Name: SwiftUIExample,interface 选 SwiftUI
在向导的第3页选择任意文件夹点击 Create 按钮创建工程

使用 MVVM 的解决方案

在工程中添加 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

在工程中添加 NumbersModifier.swift 文件,内容如下:

import SwiftUI

struct LeftModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding(8)
            .multilineTextAlignment(.trailing)
            .frame(width: 150, alignment: .trailing)
    }
}

struct RightModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .modifier(LeftModifier())
            .keyboardType(.numberPad)
            .overlay(
                RoundedRectangle(cornerRadius: 14)
                    .stroke(Color.green, lineWidth: 2)
            )
    }
}

打开 ContentView.swift 文件,将内容改为:

import SwiftUI

struct ContentView: View {
    @StateObject var vm = NumbersViewModel()
    var body: some View {
        VStack {
            HStack {
                Text("")
                    .modifier(LeftModifier())
                TextField("Number1", text: $vm.number1)
                    .modifier(RightModifier())
            }
            HStack {
                Text("")
                    .modifier(LeftModifier())
                TextField("Number2", text: $vm.number2)
                    .modifier(RightModifier())
            }
            HStack {
                Text("+")
                    .modifier(LeftModifier())
                TextField("Number3", text: $vm.number3)
                    .modifier(RightModifier())
            }
            Divider()
            HStack {
                Text("")
                    .modifier(LeftModifier())
                TextField("Result", text: $vm.result)
                    .disabled(true)
                    .modifier(RightModifier())
            }
        }.frame(width: 200, height: 200, alignment: .center)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

posted on 2022-04-29 19:17  zwvista  阅读(311)  评论(0编辑  收藏  举报