You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中fullScreenCover报错:已有有效定向事务令牌时请求新令牌

SwiftUI fullScreenCover 定向事务令牌错误解决方案

问题详情

在SwiftUI中使用fullScreenCover修饰符时触发断言错误:

"A new orientation transaction token is being requested while a valid one already exists."

错误发生在全屏视图过渡阶段(关闭当前视图并展示新视图),报错信息包含fromVC和toVC的实例引用。当前窗口与场景方向均设置为竖屏(portrait),且存在一个原始方向同样为竖屏的活跃定向事务令牌。

已尝试但无效的方案:

  • 显式设置windowOrientation与sceneOrientation
  • 将fullScreenCover包裹在NavigationStack内部
  • 展示新视图前调用presentationMode.wrappedValue.dismiss()关闭当前视图

完整报错信息

2023-06-10 21:37:10.137760+0300 SignEase[50521:19426350] [断言]
当已有有效令牌时,仍在请求新的定向事务令牌。原因=全屏过渡(正在关闭):
fromVC=<_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x13b80f200>;
toVC=<_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x13a8d7c00>;;;
windowOrientation=portrait; sceneOrientation=portrait;
existingTransaction=<__UIForcedOrientationTransactionToken: 0x280b814a0; state: active; originalOrientation: portrait (1)>

相关代码

import SwiftUI
import Firebase
import FirebaseCore
import FirebaseAuth

@available(iOS 16.0, *)
struct SignUp: View {
    @StateObject private var viewModal = SignViewData()
    @Environment(\.presentationMode) var presentationMode
    @State private var mainView = false
    @State private var SignInView = false
    
    var body: some View {
        ZStack {
            VStack(alignment: .leading){
                Text("Sign Up")
                    .font(.largeTitle)
                    .fontWeight(.bold)
                    .foregroundStyle(.linearGradient(colors: [.pink.opacity(0.6), .primary.opacity(0.5)], startPoint: .topLeading, endPoint: .bottomTrailing))
                    .padding(.leading,10)
                    .padding(.bottom,20)
                Section{
                    TextField("", text: $viewModal.text)
                        .textContentType(.emailAddress)
                        .keyboardType(.emailAddress)
                        .autocapitalization(.none)
                        .disableAutocorrection(true)
                        .placeholder(when: viewModal.text.isEmpty) {
                            Text("Email address")
                                .foregroundColor(.primary)
                                .blendMode(.overlay)
                        }
                        .customField(icon: "envelope.open.fill")
                    SecureField("", text: $viewModal.password)
                        .textContentType(.password)
                        .placeholder(when: viewModal.password.isEmpty) {
                            Text("Password")
                                .foregroundColor(.primary)
                                .blendMode(.overlay)
                        }
                        .customField(icon: "key.fill")
                    
                }
                .padding(.leading,10)
                .padding(.trailing,10)
                .padding(.bottom,10)
                
                Button {
                    Task{
                        do{
                            try await viewModal.signUp()
                            if viewModal.value == true{
                                DispatchQueue.main.async { // Add DispatchQueue.main.async block
                                    mainView.toggle()
                                }
                            }
                            return
                        }
                        catch {
                            print(error)
                        }
                    }
                } label: {
                    ButtonView(title: "Create Account")
                }
                .padding(.leading,10)
                .padding(.trailing,10)
                .fullScreenCover(isPresented: $mainView) {
// Any time i segue into this view i keep getting the error down below
                    NavigationStack{
                        RootView()
                    }
                }
                Divider()
                    .padding(5)
                    .padding(.leading,10)
                    .padding(.trailing,10)
                HStack{
                    Text("Already have an account?")
                        .font(.subheadline)
                        .foregroundStyle(.linearGradient(colors: [.pink.opacity(0.7), .primary.opacity(0.5)], startPoint: .topLeading, endPoint: .bottomTrailing))
                    Button {
                        SignInView.toggle()
                    } label: {
                        Text("Sign In")
                            .font(.subheadline)
                            .fontWeight(.semibold)
                            .foregroundColor(.black)
                    }
                }
                .fullScreenCover(isPresented:$SignInView){
                    NavigationStack{
                        SignIn()
                    }
                }
                .padding(.leading,20)
            }.padding(15)
                .frame(width: 400,height: 370)
                .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous))
                .shadow(color: Color("Shadow").opacity(0.3), radius: 10, x: 0, y: 10)
                .strokeStyle(cornerRadius: 30)
                .padding(20)
        }.background(
            Image("Background 4")
        )
    }
}

@available(iOS 16.0, *)
struct SignUp_Previews: PreviewProvider {
    static var previews: some View {
        SignUp()
    }
}

extension View {
    func placeholder<Content: View>(
        when shouldShow: Bool,
        alignment: Alignment = .leading,
        @ViewBuilder placeholder: () -> Content) -> some View {
            ZStack(alignment: alignment) {
                placeholder().opacity(shouldShow ? 1 : 0)
                self
            }
        }
}

可行解决方案

1. 延迟触发全屏视图展示

在切换状态时添加微小延迟,避开当前活跃的定向事务周期:

if viewModal.value == true {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        mainView.toggle()
    }
}

2. 使用item绑定替代布尔值触发

通过绑定Identifiable类型的可选对象来触发全屏视图,这种方式的过渡逻辑更稳定:

// 新增触发标识结构体
@State private var showRootView: RootViewTrigger?

struct RootViewTrigger: Identifiable {
    let id = UUID()
}

// 修改按钮动作
Button {
    Task{
        do{
            try await viewModal.signUp()
            if viewModal.value == true{
                DispatchQueue.main.async {
                    showRootView = RootViewTrigger()
                }
            }
            return
        }
        catch {
            print(error)
        }
    }
} label: {
    ButtonView(title: "Create Account")
}
// 修改fullScreenCover绑定方式
.fullScreenCover(item: $showRootView) { _ in
    NavigationStack{
        RootView()
    }
}

3. 检查目标视图的定向设置

确保RootView、SignInView中没有强制设置界面方向的代码(比如UIKit的preferredInterfaceOrientationForPresentation方法),避免和当前定向事务冲突。

4. 升级系统与开发工具版本

该断言错误在iOS 16早期版本中存在,升级到iOS 16.4+或Xcode 14.3+可修复部分系统层面的bug。


内容的提问来源于stack exchange,提问作者Lawal Abdulganiy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 09:37:06