【问题标题】:SwiftUI - How to change/access @Published var value via toggle from View?SwiftUI - 如何通过视图切换更改/访问@Published var 值?
【发布时间】:2021-10-26 08:02:05
【问题描述】:

我正在制作一个简单的密码生成应用程序。这个想法很简单。

视图中有 2 个切换绑定到 ObservableObject 类 2 @Published 布尔变量。单击生成按钮后,该类应根据已发布的 vars true/false 状态将不同复杂性的生成密码返回到新视图。

切换确实将已发布的 var 状态更改为 true/false(当我在切换时打印它时),并且目标视图确实显示了 false/false 组合的密码,但由于某种原因,在单击生成后,它们始终保持为 false,除非我手动将它们的值更改为 true。切换可以以某种方式永久更改@Published var 值的值吗?

我似乎找不到合适的解决方法。任何解决方案如何使这项工作?

主视图

import SwiftUI

struct MainView: View {

@ObservedObject var manager = PasswordManager()

var body: some View {
    NavigationView() {
        VStack {
            ZStack {
                Toggle(isOn: $manager.includeNumbers) {
                    Text("Include numbers")
                        .italic()
                }
            }
            ZStack {
                Toggle(isOn: $manager.includeCharacters) {
                    Text("Include special characters")
                        .italic()
                }
            }
            NavigationLink(destination: PasswordView(), label: {
                Text("Generate")
                })
        }
        .padding(80)
    }
}

密码管理器

import Foundation

class PasswordManager: ObservableObject {

    @Published var includeNumbers = false
    @Published var includeCharacters = false

    let letters = ["A", "B", "C", "D", "E"]
    let numbers = ["1", "2", "3", "4", "5"]
    let specialCharacters = ["!", "@", "#", "$", "%"]

    var password: String = ""

    func generatePassword() -> String {
    
        password = ""
    
        if includeNumbers == false && includeCharacters == false {
            for _ in 1...5 {
                password += letters.randomElement()!
            }
        }
        else if includeNumbers && includeCharacters {
            for _ in 1...3 {
                password += letters.randomElement()!
                password += numbers.randomElement()!
                password += specialCharacters.randomElement()!
            }
        }
        return password
    }
}

显示密码的视图

import SwiftUI

struct PasswordView: View {

    @ObservedObject var manager = PasswordManager()

    var body: some View {
        Text(manager.generatePassword())
    }
}

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    问题是由于您的PasswordView 创建了自己的PasswordManager 而引起的。相反,您需要从父视图注入它。

    你永远不应该在 View 内部初始化 @ObservedObject,因为每当 @ObservedObjectobjectWillChange 发出一个值时,它将重新加载视图并因此创建一个新对象。如果您的目标是 iOS 14,您需要注入 @ObservedObject 或将其声明为 @StateObject

    PasswordView 需要从PasswordManager 注入MainView,因为它们需要使用相同的实例来共享状态。在MainView 中,如果针对iOS 14,您可以使用@StateObject,否则即使在那里也应该注入PasswordManager

    import SwiftUI
    
    struct PasswordView: View {
    
        @ObservedObject private var manager: PasswordManager
    
        init(manager: PasswordManager) {
            self.manager = manager
        }
    
        var body: some View {
            Text(manager.generatePassword())
        }
    }
    
    struct MainView: View {
    
        @StateObject private var manager = PasswordManager()
    
        var body: some View {
            NavigationView() {
                VStack {
                    ZStack {
                        Toggle(isOn: $manager.includeNumbers) {
                            Text("Include numbers")
                                .italic()
                        }
                    }
                    ZStack {
                        Toggle(isOn: $manager.includeCharacters) {
                            Text("Include special characters")
                                .italic()
                        }
                    }
                    NavigationLink(destination: PasswordView(manager: manager), label: {
                        Text("Generate")
                    })
                }
                .padding(80)
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-14
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      • 2021-03-24
      • 2023-04-10
      • 2022-11-15
      相关资源
      最近更新 更多