点击NavigationLink时App冻结、CPU占用99%,求排查原因
升级Xcode到15.0并创建新项目后,在单个View内放置4-5个NavigationLink,点击跳转时App直接冻结,CPU占用率飙升至99%,必须重启App才能恢复,但重复操作问题依旧。
相关代码
SettingsView代码
struct SettingsView: View { var body: some View { VStack { Group { NavigationLink { EditProfileView() .hideNavigationBar } label: { SettingsRow(row: .editProfile) } Divider() NavigationLink { AccountVerificationView() .hideNavigationBar } label: { SettingsRow(row: .accountVerification) } Divider() NavigationLink { ChangePhoneNoView() .hideNavigationBar } label: { SettingsRow(row: .changeNumber) } Divider() } Group { SettingsRow(row: .notification, isToggleOn: $notificationOn) Divider() SettingsRow(row: .conversation, isToggleOn: $openToConversation) Divider() NavigationLink { MatchedFriends() .hideNavigationBar } label: { SettingsRow(row: .matchedFriends) } } } } }
主App代码
@main struct KoyApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationStack { SettingsView() .onOpenURL(perform: { url in Auth.auth().canHandle(url) }) } } } }
HideNavBar修饰符代码
struct HideNavBar : ViewModifier { func body(content: Content) -> some View { content .navigationBarTitle("") .navigationBarHidden(true) .navigationBarBackButtonHidden(true) } } extension View { var hideNavigationBar: some View { modifier(HideNavBar()) } }
问题排查与解决方案
1. 核心代码问题:未声明绑定状态变量
你的SettingsView中,SettingsRow(row: .notification, isToggleOn: $notificationOn)和SettingsRow(row: .conversation, isToggleOn: $openToConversation)使用了两个绑定变量$notificationOn、$openToConversation,但未在View内部声明对应的@State变量。这会导致SwiftUI在视图渲染时陷入无限循环,直接拉满CPU,引发App冻结。
修复方法:在SettingsView顶部添加这两个状态变量:
struct SettingsView: View { // 新增缺失的状态绑定变量 @State private var notificationOn = false @State private var openToConversation = false var body: some View { // 原视图代码保持不变 } }
2. NavigationStack写法优化(可选)
Xcode 15的NavigationStack对直接嵌套大量NavigationLink的场景偶尔会出现渲染冲突,虽然不是本次问题的根源,但可以改用navigationDestination的写法让代码更健壮:
struct SettingsView: View { @State private var notificationOn = false @State private var openToConversation = false @State private var selectedDestination: Destination? // 定义跳转目标枚举 enum Destination { case editProfile, accountVerification, changeNumber, matchedFriends } var body: some View { VStack { Group { Button(action: { selectedDestination = .editProfile }) { SettingsRow(row: .editProfile) } Divider() Button(action: { selectedDestination = .accountVerification }) { SettingsRow(row: .accountVerification) } Divider() Button(action: { selectedDestination = .changeNumber }) { SettingsRow(row: .changeNumber) } Divider() } Group { SettingsRow(row: .notification, isToggleOn: $notificationOn) Divider() SettingsRow(row: .conversation, isToggleOn: $openToConversation) Divider() Button(action: { selectedDestination = .matchedFriends }) { SettingsRow(row: .matchedFriends) } } } // 统一处理跳转目标 .navigationDestination(item: $selectedDestination) { destination in switch destination { case .editProfile: EditProfileView().hideNavigationBar case .accountVerification: AccountVerificationView().hideNavigationBar case .changeNumber: ChangePhoneNoView().hideNavigationBar case .matchedFriends: MatchedFriends().hideNavigationBar } } } }
3. 修饰符冗余优化(可选)
HideNavBar中的navigationBarTitle("")在iOS 14+已无必要,可简化为:
struct HideNavBar : ViewModifier { func body(content: Content) -> some View { content .navigationBarHidden(true) .navigationBarBackButtonHidden(true) } }
总结
本次问题的核心是缺失绑定状态变量导致的视图无限渲染循环,并非Xcode 15的bug。补充@State变量后即可解决冻结问题。Xcode 15的NavigationStack虽有小兼容性细节,但不是本次故障的原因。
内容的提问来源于stack exchange,提问作者Taimoor Arif
相关产品推荐
相关产品推荐

