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

SwiftUI:iPad横屏模式下NavigationSplitView在iOS16.2崩溃

这个崩溃是iOS 16.2 SwiftUI的已知bug,根源在于切换成员时,中间列的List会复用之前的实例,导致内部选择状态没有完全重置——当你从元素多的书单切换到元素少的书单时,之前选中最后一个元素的残留状态会触发内部断点。

修复方法

给中间列的List添加一个基于memberID的id修饰符,确保切换成员时List会被重新创建,彻底清空旧的选择状态:

List(books.filter({ $0.memberId == memberID }), selection: $bookID) { book in
    Text(book.name)
}
.id(memberID) // 新增这一行

完整修改后的代码

//
//  ContentView.swift
//  test
//

import SwiftUI

struct Member: Hashable, Identifiable {
    var id: Int
    var name: String
}

struct Book: Hashable, Identifiable {
    var id: Int
    var memberId: Int
    var name: String
}

struct ContentView: View {
    @State private var memberID: Member.ID?
    @State private var bookID: Book.ID?
    @State private var columnVisibility = NavigationSplitViewVisibility.all
    
    var members = [
        Member(id:1, name:"George"),
        Member(id:2, name:"John"),
        Member(id:3, name:"Luca"),
    ]
    
    var books = [
        Book(id:1,memberId:1, name:"A good Book"),
        Book(id:2, memberId:1, name:"Another great Book"),
        Book(id:3, memberId: 1, name:"Very good Book"),
        Book(id:4,memberId:1, name:"Lame Book"),
        Book(id:5, memberId:1, name:"Big Book"),
        Book(id:6, memberId: 2, name:"Small Book"),
        Book(id:7,memberId:2, name:"Green Book"),
        Book(id:8, memberId:2, name:"Yellow Book"),
        Book(id:9, memberId: 3, name:"Boring Book"),
        Book(id:10, memberId: 3, name:"Best Book"),
    ]
    
    var body: some View {
        NavigationSplitView(columnVisibility: $columnVisibility) {
            List(members, selection: $memberID) { member in
                HStack{
                    Text("ID: \(member.id)")
                    Text("Name: \(member.name)")
                }
            }
        } content: {
            if memberID == nil {
                Text("select")
            } else {
                List(books.filter({ $0.memberId == memberID }), selection: $bookID) { book in
                    Text(book.name)
                }
                .id(memberID) // 新增的id修饰符
            }
        } detail: {
            Text("Details")
        }
        .onChange(of: memberID){ _ in
            bookID = nil
        }
    }
}

为什么这个方法有效

虽然你已经在onChange里把bookID设为nil,但SwiftUI的List内部还会维护一些私有状态(比如滚动位置、选中索引的缓存)。当切换到元素更少的列表时,这些旧状态会导致内部逻辑出错。通过给List绑定memberID作为唯一标识,每次切换成员时SwiftUI都会销毁旧List并创建新实例,彻底清除所有旧状态,从而避免崩溃。

这个问题在iOS 16.3及以上版本已经被苹果修复,如果你能升级部署目标版本,也可以通过系统更新解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:45:01