使用 Combine 和 SwiftUI 对点击的按钮进行更改

Posted

技术标签:

【中文标题】使用 Combine 和 SwiftUI 对点击的按钮进行更改【英文标题】:Get changes on button tapped using Combine and SwiftUI 【发布时间】:2020-09-24 10:05:48 【问题描述】:

在用户从Menu 中选择正确的位置后尝试更改isValid

如果我先选择一个职位,然后在文本字段中输入电子邮件和姓名而不是另一边,这似乎可以工作。

我想在他选择位置并填写其他文本字段时启用Button

class EmployeeModel: ObservableObject
    
    @Published var employee: Employee
    @Published var isValid = false
    
    private var cancellables = Set<AnyCancellable>()
    
    init(employee: Employee = Employee(uid: "", affiliate: 0, employeeID: 1, email: "", name: "", shiftsConstIsApplied: false, position: nil, shiftConsts: nil, pushId: ""))
        
        self.employee = employee
        
        self.$employee
            .debounce(for: 0.5, scheduler: RunLoop.main)
            
            .map(!$0.name.isEmpty && !$0.email.isEmpty && $0.position != nil)
            .sink input in
                print(input)
                self.isValid = input
            
            .store(in: &cancellables)
    

观点:


@State private var position: Positions?
@StateObject var employeeModel = EmployeeModel()

Menu(LocalizedStringKey(self.$position.wrappedValue?.rawValue ?? "Choose position")) 
                        ForEach(Positions.employeeTypes, id:\.self) p in
                            Button(LocalizedStringKey(p))
                                let positionSelected = Positions(rawValue: p)
                                self.position = positionSelected
                                self.employeeModel.employee.position = positionSelected
                            
                        
                    

Button("Confirm")
//do something

.disabled(!self.employeeModel.isValid)

将员工建模为 ObservableObject:

    @Published var uid: String?
    @Published var email: String
    @Published var name: String
    @Published var affiliate: Int?
    @Published var employeeId: Int?
    @Published var shiftsConstIsApplied: Bool? = true
    @Published var position: Positions?
    @Published var shiftConsts: [ShiftConst]?

【问题讨论】:

【参考方案1】:

如果我正确理解了您的代码,请尝试以下操作(未经测试!)

init(employee: Employee = Employee(uid: "", affiliate: 0, employeeID: 1, email: "", name: "", shiftsConstIsApplied: false, position: nil, shiftConsts: nil, pushId: ""))
    
    self.employee = employee
    
    self.employee.objectWillChange               // << here !!
        .debounce(for: 0.5, scheduler: RunLoop.main)

,你不会改变employee本身(因为它是引用类型),只是改变它的内部属性,所以你需要订阅它的内部发布者。

【讨论】:

我想从self.employee 的内部属性中更改isValid。用户输入姓名和邮箱后,需要选择职位,目前,当用户选择职位isValid仍然=false。但是,如果我再次输入电子邮件或姓名(甚至只是添加一个字符),它就会起作用。我希望它在他选择职位后立即起作用。

以上是关于使用 Combine 和 SwiftUI 对点击的按钮进行更改的主要内容,如果未能解决你的问题,请参考以下文章

将 AppKit/UIKit 中的 Key-Value Observation 转换为 Combine 和 SwiftUI

使用 Combine 和 SwiftUI 显示变化值的最简洁方式是啥?

如何使用 Combine 框架和 SwiftUI 发布网络请求的数据

如何使用 SwiftUI 和 Combine 检测 Datepicker 的值变化?

在 SwiftUI 中使用 Combine 进行映射、捕获错误和分配

使用 Combine 和 SwiftUI 在 Realm 中观察收集结果