所以我最初的问题问如何禁用导航链接,并且仅在影响两个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.
我也得到了在模拟器上运行的错误消息,但是NavigationLink
从未启用。
我正在2016 Macbook Pro的Catalina 5 beta上运行Xcode 5 beta。删除派生数据,重新启动Xcode,重新启动计算机,重置模拟器,更改模拟器,无济于事。按下第一个invalid mode 'kCFRunLoopCommonModes'
时,我仍然看到Toggle
,并且NavigationLink
从未启用。
所以新的问题是:
invalid mode 'kCFRunLoopCommonModes'
导致我绑定到@State
的{{1}}永远不会成为Toggle
的问题?使用XCode 11 beta 5和SwiftUI。在true
中,我有两个WelcomeScene
视图,一个视图用于接受条款和条件,另一个用于隐私政策。这些切换分别更新两个单独的Toggle
属性。
在场景的底部,我有一个@State
(按钮),它将转到下一个场景,我希望默认情况下 禁用 。 >,并且只有在 NagivationLink
和hasAgreedToTermsAndConditions
的状态均为hasAgreedToPrivacyPolicy
时,才能启用 。
启动true
时,会有一个NavigationLink
参数,它带有一个isActive
,听起来像是对的。但是,Binding<Bool>
属性不能标记为@Binding
,因此我不能使其成为依赖于lazy
和hasAgreedToTermsAndConditions
的计算属性。
还有一个hasAgreedToPrivacyPolicy
视图修饰符,它使用disabled
,这也是不正确的,因为它没有被更新...
Bool
当两个切换均为struct WelcomeScene: View {
@State var hasAgreedToTermsAndConditions: Bool = false
@State var hasAgreedToPrivacyPolicy: Bool = false
var body: some View {
VStack {
Image(named: "MyImage")
Spacer()
Text("Welcome friend!".uppercased())
.font(.system(size: 55))
Toggle(isOn: $hasAgreedToTermsAndConditions) {
Text("I agree to the Terms and Conditions")
}.toggleStyle(DefaultToggleStyle())
Toggle(isOn: $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...
NavigationLink("Proceed", destination: SignInScene(), isActive: ($hasAgreedToTermsAndConditions && $hasAgreedToPrivacyPolicy))
}.padding(30)
}
}
时,如何默认设置NavigationLink
disabled
并仅设置enabled
?
答案 0 :(得分: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")
}
}
答案 1 :(得分:0)
这里的主要问题是您误解了所使用的NavigationLink
初始化的含义。
/// Creates an instance that presents `destination` when active, with a
/// `Text` label generated from a title string.
public init(_ titleKey: LocalizedStringKey, destination: Destination, isActive: Binding<Bool>)
isActive
并不意味着仅当布尔值为true时,链接才可单击。这意味着您正在创建一个NavigationLink
,当单击并在 isActive
绑定变为true时触发导航两者。
您可以通过disabled
修饰符来实现所需的目标:
struct WelcomeScene: View {
@State var hasAgreedToTermsAndConditions: Bool = false
@State var hasAgreedToPrivacyPolicy: Bool = false
var body: some View {
NavigationView {
VStack {
Spacer()
Toggle(isOn: $hasAgreedToTermsAndConditions) {
Text("I agree to the Terms and Conditions")
}.toggleStyle(DefaultToggleStyle())
Toggle(isOn: $hasAgreedToPrivacyPolicy) {
Text("I agree to the Privacy Policy")
}.toggleStyle(DefaultToggleStyle())
NavigationLink("Proceed", destination: SignInScene())
.disabled(!hasAgreedToTermsAndConditions || !hasAgreedToPrivacyPolicy)
}.padding(30)
}
}
}