iOS 16 Core Data日记应用地图视图更新问题(设备正常模拟器异常)
问题:iOS日记应用中使用FindLocationView后地图未即时更新(仅模拟器问题)
我正在开发一款基于Core Data存储日记条目的iOS简易应用,目标系统为iOS 16,采用NavigationSplitView作为核心布局。每个日记条目支持可选位置,数据模型存储纬度、经度以及标记位置是否存在的布尔值,对应位置需展示地图。
调整代码结构,将位置与地图坐标区域的逻辑迁移到JournalEntryView后,出现了以下问题:用户点击「Find」按钮打开FindLocationView添加位置后,地图视图不会即时更新,仍显示旧位置;但切换到其他条目再返回后,地图就能正常显示新位置。原本预期onDismiss方法会触发地图更新,但并未生效。
后续验证发现,该问题仅在iOS模拟器中存在,真实设备上运行完全正常,目前问题已解决。
ContentView代码
struct ContentView: View { @Environment(\.managedObjectContext) private var viewContext @FetchRequest( sortDescriptors: [NSSortDescriptor(keyPath: \DailyEntry.timestamp, ascending: true)], animation: .default) private var items: FetchedResults<DailyEntry> @State private var searchPredicate = NSPredicate { _, _ in true } @State private var selectedItem: DailyEntry? @State private var columnVisibility = NavigationSplitViewVisibility.all @State private var searchString = "" var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { List { ForEach(items) { item in Button { selectedItem = item columnVisibility = .automatic } label: { Text(item.timestamp, style: .date) } } .onDelete(perform: deleteItems) } .searchable(text: $searchString) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { EditButton() } ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } detail: { if let item = selectedItem { JournalEntryView(entry: item) } else { HStack { Spacer() Text("Select a journal entry or create a new one") } .padding() } } .onSubmit(of: .search) { searchPredicate = ... items.nsPredicate = searchPredicate } .onChange(of: searchString) { newValue in if newValue == "" { items.nsPredicate = nil } } } private func addItem() { ... } private func deleteItems(offsets: IndexSet) { ... } }
JournalEntryView代码
struct JournalEntryView: View { @Environment(\.managedObjectContext) private var viewContext @ObservedObject var entry: DailyEntry @ObservedObject var locationManager = sharedLocationManager @State private var locationRequested = false @State private var locationPickerShowing = false @State private var mapRegion: MKCoordinateRegion = MKCoordinateRegion() @State private var mapLocation = CLLocationCoordinate2D() init(entry: DailyEntry) { self.entry = entry mapLocation = CLLocationCoordinate2D(latitude: entry.latitude, longitude: entry.longitude) mapRegion = MKCoordinateRegion(center: mapLocation, span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)) } var body: some View { VStack(alignment: .leading) { HStack { DatePicker("Date:", selection: $entry.timestamp, displayedComponents: [.date]) VStack { if entry.hasLocation { Map(coordinateRegion: $mapRegion, annotationItems: [IdentifiablePlace(location: mapLocation)]) { place in MapMarker(coordinate: place.location) } } HStack { TextField("Location name", text: $entry.placeName) Button("Find") { locationPickerShowing = true } LocationButton(.currentLocation) { locationManager.getLocation() locationRequested = true } } } } ... } .padding() .onAppear() { setMap(latitude: entry.latitude, longitude: entry.longitude) } .onChange(of: locationManager.currentLocation) { newValue in if locationRequested { entry.latitude = locationManager.currentLocation.coordinate.latitude entry.longitude = locationManager.currentLocation.coordinate.longitude entry.hasLocation = true locationRequested = false setMap(latitude: entry.latitude, longitude: entry.longitude) } } .onChange(of: entry) { newValue in biblePassage = newValue.bibleSelection() if newValue.hasLocation { setMap(latitude: newValue.latitude, longitude: newValue.longitude) } } .sheet(isPresented: $locationPickerShowing, onDismiss: { setMap(latitude: entry.latitude, longitude: entry.longitude) }) { FindLocationView(entry: entry, isPresented: $locationPickerShowing, searchString: entry.placeName) } } func setMap(latitude: Double, longitude: Double) { if entry.hasLocation { let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) mapRegion = MKCoordinateRegion(center: coordinate, span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)) mapLocation = coordinate } } }
FindLocationView代码
struct FindLocationView: View { @Environment(\.managedObjectContext) private var viewContext @ObservedObject var entry: DailyEntry @Binding var isPresented: Bool @State var searchString: String @State private var location: CLLocationCoordinate2D? @State private var locationList: [CLPlacemark] = [] @State private var placeMark: CLPlacemark? var body: some View { VStack(alignment: .leading) { Text("Enter a name:") HStack { TextField("Name", text: $searchString, prompt: Text("City, town, village")) .onSubmit(of: .text) { lookupLocation() } Button("Search") { lookupLocation() } } List(selection: $placeMark) { ForEach(locationList, id: \.self) { place in let name = place.name ?? "" let country = place.country ?? "" let display = name == "" ? country : "\(name), \(country)" Text(display) } } HStack { Spacer() Button("OK") { if let newLocation = placeMark?.location { entry.latitude = newLocation.coordinate.latitude entry.longitude = newLocation.coordinate.longitude entry.hasLocation = true entry.placeName = placeMark?.name ?? searchString } isPresented = false } } } .padding() .onAppear() { if searchString != "" { lookupLocation() } } } func lookupLocation() { let geocoder = CLGeocoder() geocoder.geocodeAddressString(searchString) { placeMarks, error in if let placeMarks = placeMarks { locationList = placeMarks } } } }
内容的提问来源于stack exchange,提问作者Mussau
相关产品推荐
相关产品推荐

