SwiftUI传递正确GroupT却获取错误Carpool ID的问题排查
问题描述
开发SwiftUI应用时,为特定拼车组(GroupT)获取事件数据时遇到问题:CalendarCell视图始终获取默认组的事件,即便传入了含正确Carpool ID的GroupT对象。
预期行为:选择拼车组后,CalendarCell应使用该组的Carpool ID拉取事件,但EventViewModel中使用的ID始终是最新创建组的ID,目前通过UserDefaults获取Carpool ID。
CalendarCell视图代码
struct CalendarCell: View { let group: GroupT @StateObject var eventViewModel: EventViewModel @State private var events: [Event] = [] @State private var isShowingDailyEventPage = false init(group: GroupT) { self.group = group _eventViewModel = StateObject(wrappedValue: EventViewModel(group: group)) // 用所选组初始化EventViewModel } var body: some View { Text("Some Day") .onTapGesture { fetchDailyEvents() } } func fetchDailyEvents() { guard let carpoolIDString = UserDefaults.standard.string(forKey: "carpoolID") else { print("Carpool ID not found in UserDefaults") return } let joinCode = group.joinCode printCarpoolID() print("Retrieved Carpool ID from UserDefaults: \(carpoolIDString)") guard let carpoolID = UUID(uuidString: carpoolIDString) else { print("Invalid UUID string for Carpool ID: \(carpoolIDString)") return } print("Valid Carpool ID: \(carpoolID.uuidString)") let viewModel = EventViewModel(group: GroupT(carpoolID: carpoolID, carpoolName: "Example", admin: "admin", date_created: Date(), members: [], events: [], joinCode: joinCode)) viewModel.fetchDailyEvents(forCarpoolID: carpoolID.uuidString, date: dateForCell()) { result in switch result { case .success(let events): DispatchQueue.main.async { self.events = events } case .failure(let error): print("Error fetching events: \(error)") } } } }
EventViewModel方法代码
func fetchDailyEvents(forCarpoolID carpoolID: String, date: Date, completion: @escaping (Result<[Event], Error>) -> Void) { // DateFormatter for the date string in ISO 8601 format let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" // API expects this date format let dateString = dateFormatter.string(from: date) // Lowercase carpoolID for consistency let lowercasedCarpoolID = carpoolID.lowercased() // Debugging: Print carpool ID and formatted date print("Fetching events for Carpool ID: \(lowercasedCarpoolID) on Date: \(dateString)") // Construct the API URL guard let apiURL = URL(string: "http://localhost/api/events/\(lowercasedCarpoolID)/date/\(dateString)") else { print("Invalid API URL") completion(.failure(NetworkError.invalidRequest)) return } // Debugging: Print the constructed API URL print("Constructed API URL: \(apiURL)") // Create URLRequest var request = URLRequest(url: apiURL) request.httpMethod = "GET" request.setValue("application/json", forHTTPHeaderField: "Content-Type") // Perform the network request let task = URLSession.shared.dataTask(with: request) { data, response, error in // Handle potential errors if let error = error { print("Network error: \(error.localizedDescription)") completion(.failure(NetworkError.invalidResponse)) return } // Print the HTTP response status code if let httpResponse = response as? HTTPURLResponse { print("HTTP Response Status Code: \(httpResponse.statusCode)") } // Ensure data is not nil guard let data = data else { print("No data received") completion(.failure(NetworkError.invalidResponse)) return } // Debugging: Print the raw JSON response if let jsonString = String(data: data, encoding: .utf8) { print("Received JSON: \(jsonString)") } do { // Decode the response as an array of Event let decoder = JSONDecoder() decoder.dateDecodingStrategy = .iso8601 // API uses ISO 8601 for date and time // Attempt decoding let events = try decoder.decode([Event].self, from: data) // Debugging: Print the decoded events print("Successfully decoded events: \(events)") completion(.success(events)) } catch { // Print detailed decoding error information print("Decoding error: \(error.localizedDescription)") completion(.failure(error)) } } task.resume() }
GroupT结构体代码
struct GroupT: Codable { let carpoolID: UUID let carpoolName: String let admin: String var members: [String] let date_created: Date let events: [Event] let joinCode: String }
已尝试步骤
- 确认传入
CalendarCell的group为正确所选组; - 在
fetchDailyEvents中打印Carpool ID,确认其正确性; - 视图仍使用最新创建组的错误ID拉取事件;
- 确认Carpool ID已正确保存到
UserDefaults,但获取异常。
解决方案
问题根源
- 错误依赖UserDefaults:
fetchDailyEvents中从UserDefaults取的Carpool ID未随组选择更新,或始终存储最新创建组的ID,导致用错ID; - 重复创建ViewModel:初始化
CalendarCell时已用传入的group创建@StateObject的eventViewModel,但fetchDailyEvents里又新建临时实例,完全未复用正确的ViewModel; - 硬编码GroupT实例:新建临时ViewModel时手动构造
GroupT,用的是UserDefaults的ID而非传入组的真实数据。
修复步骤
- 直接使用传入组的Carpool ID:删除
UserDefaults相关逻辑,直接用group.carpoolID,这是当前选中组的正确ID; - 复用已有的EventViewModel:不要新建临时实例,直接用初始化好的
eventViewModel调用方法; - 清理冗余代码:删掉手动构造
GroupT的无效代码。
修改后的fetchDailyEvents代码:
func fetchDailyEvents() { let carpoolID = group.carpoolID.uuidString print("Using Carpool ID from selected group: \(carpoolID)") eventViewModel.fetchDailyEvents(forCarpoolID: carpoolID, date: dateForCell()) { result in switch result { case .success(let events): DispatchQueue.main.async { self.events = events } case .failure(let error): print("Error fetching events: \(error)") } } }
额外建议
- 若需用
UserDefaults存储当前选中组ID,必须在用户切换组时立即更新该值;但更可靠的方式是直接通过视图传递的group对象获取ID,避免依赖全局状态; - 检查
EventViewModel初始化逻辑,确保正确接收并保存传入的group信息,方便后续使用组的其他数据。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

