在模拟器/预览版上运行的 SwiftUI:切换不起作用,控制台日志:“无效模式 'kCFRunLoopCommonModes'”

Saj*_*jon 7 xcode swift swiftui

更新:这是一条红鲱鱼

所以我最初的问题是问如何禁用导航链接,并且仅当Toggle影响两个@State var isXYZToggleOn Bool属性的两个属性都为true时才启用。这一直有效,我第一次尝试使用的.disabled(!(hasAgreedToTermsAndConditions && hasAgreedToPrivacyPolicy))是正确的(@superpuccio 也建议,但使用两个否定和一个布尔值或 ( ||))。

轮到我没有NavigationLink启用我的,因为切换不起作用,而不是因为布尔值和disabled视图修饰符的不正确使用。

在设备上运行,而不是模拟器使一切正常!但是我一按任何Toggle(但只有一次)仍然会看到警告消息:

invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
Run Code Online (Sandbox Code Playgroud)

我也在模拟器上运行时收到此错误消息,但随后NavigationLink从未启用。

我在 2016 Macbook Pro 上的 Catalina 5 beta 上运行 Xcode 5 beta。删除派生数据,重新启动Xcode,重新启动我的电脑,重置模拟器,更改模拟器,没有任何帮助。invalid mode 'kCFRunLoopCommonModes'当我按下第一个时我仍然看到Toggle,并且NavigationLink永远不会启用。

所以新的问题是:

在模拟器上运行:如何解决invalid mode 'kCFRunLoopCommonModes'导致我的@State绑定Toggle永远不会成为的问题true

原始问题

使用 XCode 11 beta 5 和 SwiftUI。在WelcomeScene我有两种Toggle观点,一种是接受条款和条件的切换开关,另一种是隐私政策的切换开关。这些切换@State分别更新两个单独的属性。

在现场的底部我有一个NagivationLink(按钮),将采取下一个场景,我想被禁用默认情况下,只有被激活 hasAgreedToTermsAndConditionshasAgreedToPrivacyPolicy状态是true

启动 a 时NavigationLink有一个isActive参数,它采用 a Binding<Bool>,这听起来是正确的。但是,@Binding属性不能被标记lazy,因此我不能使它成为依赖于hasAgreedToTermsAndConditions和的计算属性hasAgreedToPrivacyPolicy

还有一个disabled视图修饰符,它采用Bool,这也是不正确的,因为它没有得到更新......

invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
Run Code Online (Sandbox Code Playgroud) 我怎样才能NavigationLink disabled在默认情况下制作 a并且只有enabled当两个切换都是on

Fab*_*ian 0

我没有找到任何方法从某个州获得出版商,因此有必要将内容转移到ObservableObject. 从@Published项目中,我们可以通过 访问它的发布者$hasAgreedToPrivacyPolicy,可以将其用于诸如Publishers.CombineLatest组合两个发布者值并基于该设置的其他变量之类的事情。

两个导航链接是必要的,因为一旦其中一个链接处于活动状态,使其处于非活动状态并不会隐藏详细信息视图中显示的内容。第二个基本上是为了显示内容,但条款尚未被接受。

注意:此处显示的是分割视图(使用NavigationLink嵌入NavigationView)。您还可以使用 .sheet (由 控制isActive)或条件在视图之间切换。

import SwiftUI
import Combine

class Settings: ObservableObject {
    @Published var hasAgreedToTermsAndConditions: Bool = false
    @Published var hasAgreedToPrivacyPolicy: Bool = false

    @Published var isActive = false
    @Published var isNotActive = true

    private var cancellable: AnyCancellable? = nil

    init() {
        self.cancellable = Publishers.CombineLatest($hasAgreedToPrivacyPolicy, $hasAgreedToTermsAndConditions).map{
            return $0.0 && $0.1
        }.sink{
            self.isActive = $0
            self.isNotActive = !$0
        }
    }
}

struct WelcomeSceneView: View {
    @ObservedObject var settings = Settings()

    var body: some View {
        NavigationView {
            VStack {
                Image(uiImage: welcomeLogo)

                Spacer()

                Text("Welcome friend!".uppercased())
                //.font(.system(size: 55))

                Toggle(isOn: $settings.hasAgreedToTermsAndConditions) {
                    Text("I agree to the Terms and Conditions")
                }.toggleStyle(DefaultToggleStyle())

                Toggle(isOn: $settings.hasAgreedToPrivacyPolicy) {
                    Text("I agree to the Privacy Policy")
                }.toggleStyle(DefaultToggleStyle())


                // This does not compile 'Binding<Bool> is not convertible to Bool', but I cannot figure out how to create a compupted property binding using those 2 states...
                Text("is active: \(settings.isActive.description)")
                NavigationLink("Can proceed", destination: SignInScene(), isActive: $settings.isActive)
                .hidden()
                NavigationLink("Can not proceed", destination: PleaseConfirmView(), isActive: $settings.isNotActive)
                .hidden()
            }.padding(30)
        }
    }

    let welcomeLogo = UIImage(systemName: "headphones")!
}

struct SignInScene: View {
    var body: some View {
        Text("Some sign in scene")
    }
}

struct PleaseConfirmView: View {
    var body: some View {
        Text("Please confirm")
    }
}
Run Code Online (Sandbox Code Playgroud)