Sheet关闭后ObservableObject变更偶尔无法同步至视图
解决SwiftUI中@AppStorage结合ObservableObject更新视图不及时的问题
问题根源
你当前的实现存在核心问题:LocationView和LocationSearch各自创建了独立的SavedLocations实例。虽然@AppStorage会将数据持久化到UserDefaults,但ObservableObject的变更通知仅作用于当前实例,另一个实例无法实时感知数据变化,这就导致了新增位置后视图偶尔不刷新的情况。
解决方案
方案1:传递同一SavedLocations实例
让LocationSearch复用LocationView中的SavedLocations实例,而非新建,这样数据变更会直接触发两个视图同步刷新。
修改LocationSearch代码
struct LocationSearch: View { @Environment(\.dismiss) var dismiss @StateObject var locationService = LocationService() @ObservedObject var networking: Networking // 改为接收外部传入的实例,不再自行创建 @ObservedObject var savedLocations: SavedLocations @State var showAlert = false var body: some View{ Form { // 原有代码保留 Section { List { ForEach(locationService.searchResults, id: \.self) { completionResult in Button("\(completionResult.city), \(completionResult.country)") { networking.getCoordinate(addressString: completionResult.city) { coordinates, error in if error == nil { networking.lastLocation = CLLocation(latitude: coordinates.latitude, longitude: coordinates.longitude) DispatchQueue.main.async() { let newLocation = Location(name: completionResult.city) savedLocations.all.append(newLocation) savedLocations.all = savedLocations.all.unique() dismiss() } } else { print("Error setting custom location: \(String(describing: error))") showAlert.toggle() } } } } } } } } }
修改LocationView中Sheet的调用代码
.sheet(isPresented: $showingSheet) { // 传入当前视图的savedLocations实例 LocationSearch(networking: networking, savedLocations: savedLocations) }
方案2:将SavedLocations改为单例
如果需要在多个视图中共享该实例,可以将其设计为单例,确保全局只有一个实例存在:
class SavedLocations: ObservableObject { // 单例实例 static let shared = SavedLocations() private init() {} @AppStorage("Locations") var all = [Location]() func deleteLocation(at offsets: IndexSet) { all.remove(atOffsets: offsets) } }
然后在视图中使用单例:
LocationView中:@StateObject var savedLocations = SavedLocations.sharedLocationSearch中:@ObservedObject var savedLocations = SavedLocations.shared
额外注意事项
Location类型需要遵循Equatable协议,因为你在ForEach中使用了id: \.self,确保SwiftUI能正确识别列表元素的变化。- 自定义类型存储到
@AppStorage时,需要遵循RawRepresentable协议,将类型转换为Data或其他可存储的原始类型,避免持久化失败。
内容的提问来源于stack exchange,提问作者John Harrington
相关产品推荐
相关产品推荐

