Swift+Alamofire实现事件按距离及日期排序并筛选近一周事件求助
Hey there! Since you’ve already got location and distance sorting working with Alamofire, let’s build on that to add the date-based filtering and sorting you need. Here’s a step-by-step breakdown tailored to your setup:
1. Prep Your Event Model for Date Handling
Assuming you have a Codable model for your events (if not, you’ll want one to parse the JSON cleanly), add computed properties to extract and validate the event dates from your eventDate1 to eventDate5 fields:
import Foundation // First, define a reusable date formatter (match this to your JSON date format!) let eventDateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" // Replace with your actual JSON date string format formatter.locale = Locale(identifier: "en_US_POSIX") formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter }() struct Event: Codable { // Your existing properties (id, name, location coords, etc.) let eventDate1: String? let eventDate2: String? let eventDate3: String? let eventDate4: String? let eventDate5: String? // Get all valid Date objects from the 5 date fields (ignore nil/invalid strings) var validEventDates: [Date] { let dateStrings = [eventDate1, eventDate2, eventDate3, eventDate4, eventDate5] return dateStrings.compactMap { dateStr in guard let str = dateStr else { return nil } return eventDateFormatter.date(from: str) } } // Get the most relevant date for sorting/filtering (adjust based on your needs: // - Use max() for the latest event date // - Use min() for the earliest // - Or custom logic to pick the date closest to now) var primaryEventDate: Date? { return validEventDates.max() // Using latest date as primary } }
2. Add Date Filtering Logic
We’ll filter events to only include those with at least one date that falls within your required range: no earlier than 1 week ago, and no later than the event’s own date (note: the "no later than event date" check is redundant since the date is the event’s own date—if you meant "no later than today", just replace date <= date with date <= Date()).
// Calculate the cutoff date (1 week before now) let oneWeekAgo = Calendar.current.date(byAdding: .day, value: -7, to: Date())! // Filter your events array (after parsing from Alamofire response) let filteredEvents: [Event] = yourAlamofireEventsArray.filter { event in // Check if any of the event's valid dates meet the criteria return event.validEventDates.contains { date in date >= oneWeekAgo && date <= date // Adjust to date <= Date() if you mean "no later than today" } }
3. Implement Date Sorting
Now sort the filtered events by their primary date (latest first, or earliest first—adjust the comparison as needed):
// Sort filtered events by primary date (latest first) let sortedByDateEvents = filteredEvents.sorted { eventA, eventB in guard let dateA = eventA.primaryEventDate, let dateB = eventB.primaryEventDate else { // Handle events with no valid dates (e.g., push them to the end of the list) return false } return dateA > dateB // Reverse to dateA < dateB for earliest first }
4. Integrate with Existing Distance Sorting
If you want to toggle between distance and date sorting, wrap everything in a helper function that takes a sort option:
import CoreLocation enum SortType { case distance(userLocation: CLLocation) case date } func sortAndFilterEvents(events: [Event], by sortType: SortType) -> [Event] { // First apply date filter let oneWeekAgo = Calendar.current.date(byAdding: .day, value: -7, to: Date())! let filtered = events.filter { $0.validEventDates.contains { $0 >= oneWeekAgo && $0 <= Date() } // Adjusted to "no later than today" as a likely intended behavior } // Apply sorting based on selected type switch sortType { case .distance(let userLocation): // Your existing distance sorting logic return filtered.sorted { eventA, eventB in let locA = CLLocation(latitude: eventA.lat, longitude: eventA.lng) // Replace with your event's location properties let locB = CLLocation(latitude: eventB.lat, longitude: eventB.lng) return locA.distance(from: userLocation) < locB.distance(from: userLocation) } case .date: return filtered.sorted { guard let dA = $0.primaryEventDate, let dB = $1.primaryEventDate else { return false } return dA > dB } } } // Usage example: // let sortedByDate = sortAndFilterEvents(events: yourEventsArray, by: .date) // let sortedByDistance = sortAndFilterEvents(events: yourEventsArray, by: .distance(userLocation: userCurrentLocation))
Key Adjustments for Your Setup
- Date Format: Make sure
eventDateFormatteruses the exact format of your JSON date strings (common formats include"yyyy-MM-dd"or"MM/dd/yyyy HH:mm"). - Primary Date Logic: Adjust the
primaryEventDatecomputed property if you need to use a different date (e.g., earliest date instead of latest, or the date closest to the user’s current time). - Filter Edge Cases: If you want to exclude events with no valid dates entirely, add a check to the filter:
!event.validEventDates.isEmpty && ....
Let me know if you need help tweaking any part to fit your specific model structure or JSON format! 😊
内容的提问来源于stack exchange,提问作者Geoff

