Swift中基于MapKit获取地点扩展信息的方案咨询
问题:获取POI更多信息(图片、营业时间)的实现方案
我现有一段基于查询字符串搜索附近地点的Swift代码,搜索特定餐厅会得到如下MKMapItem结果:
<MKMapItem: 0x301095d00> { isCurrentLocation = 0; name = "Chick-fil-A"; phoneNumber = "+1 (707) 421-9631"; placemark = "Chick-fil-A, 1750 Travis Blvd, Fairfield, CA 94533, United States @ <+38.25884980,-122.05986700> +/- 0.00m, region CLCircularRegion (identifier:'<+38.25884981,-122.05986700> radius 141.17', center:<+38.25884981,-122.05986700>, radius:141.17m)"; timeZone = "America/Los_Angeles (PDT) offset -25200 (Daylight)"; url = "https://www.chick-fil-a.com/locations/ca/fairfield-in-line-dt";}
对应的实现代码:
import MapKit import CoreLocation class AddressSearchViewModel: NSObject, ObservableObject, MKLocalSearchCompleterDelegate { @Published var searchResults: [searchLoc] = [] @Published var searching: Bool = false private var searchCompleter: MKLocalSearchCompleter! override init() { super.init() searchCompleter = MKLocalSearchCompleter() searchCompleter.delegate = self searchCompleter.resultTypes = [.address, .pointOfInterest] } func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) { getCityList(results: completer.results) { cityResults in DispatchQueue.main.async { self.searching = false cityResults.forEach { element in if !self.searchResults.contains(where: { $0.searchName == element.searchName }) { self.searchResults.insert(element, at: 0) } } } } } func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) { } func performSearch(queryStr: String) { searching = true self.searchCompleter.queryFragment = queryStr } private func getCityList(results: [MKLocalSearchCompletion], completion: @escaping ([searchLoc]) -> Void) { var searchTemp: [searchLoc] = [] let dispatchGroup = DispatchGroup() for result in results { dispatchGroup.enter() let request = MKLocalSearch.Request(completion: result) let search = MKLocalSearch(request: request) search.start { (response, error) in defer { dispatchGroup.leave() } guard let response = response else { return } for item in response.mapItems { if let name = item.name { searchTemp.append(searchLoc(searchName: name, lat: item.placemark.coordinate.latitude, long: item.placemark.coordinate.longitude)) } } } } dispatchGroup.notify(queue: .main) { completion(searchTemp) } } } // 补充缺失的模型定义 struct searchLoc { let searchName: String let lat: Double let long: Double }
以餐厅为例,如何获取该地点的图片、营业时间等更多信息?是否可以使用原生Swift API实现此需求?或是谷歌地图API为最优替代方案?
解决方案
一、原生MapKit的能力限制与可用功能
1. 营业时间获取
原生MKMapItem自带openingHours属性(类型为MKOpeningHours),可直接提取营业时间相关信息:
// 在遍历response.mapItems时扩展逻辑 for item in response.mapItems { if let name = item.name { // 获取营业时间对象 let openingHours = item.openingHours // 判断当前是否营业 let isOpenNow = openingHours?.isOpen() ?? false // 获取格式化的营业时间文本(短格式/长格式可选) let formattedHours = openingHours?.formattedOpeningHours(style: .short) // 更新模型存储额外信息 let location = searchLoc( searchName: name, lat: item.placemark.coordinate.latitude, long: item.placemark.coordinate.longitude, isOpenNow: isOpenNow, openingHours: formattedHours ) searchTemp.append(location) } } // 扩展模型结构 struct searchLoc { let searchName: String let lat: Double let long: Double let isOpenNow: Bool? let openingHours: String? }
注意:部分POI可能没有录入营业时间数据,需做可选值安全处理。
2. 图片获取
原生MapKit没有直接获取POI图片的官方API,这是原生方案的核心短板,无法通过Apple提供的接口获取餐厅、景点等地点的图片资源。
二、谷歌地图Places API的优势
如果需要图片或更全面的POI数据,谷歌地图Places API是更优选择:
- 支持通过Place ID请求POI图片(最多可获取10张不同角度的资源)
- 营业时间数据覆盖更广,支持节假日特殊时段信息
- 提供额外字段:用户评分、价格等级、详细分类标签等
- 全球数据覆盖更均衡,部分地区Apple Maps数据完善度不及谷歌
三、方案选择建议
- 若仅需营业时间、基础地点信息,优先用原生MapKit,无需额外API密钥,集成成本更低
- 若必须获取图片或更丰富的POI数据,建议接入谷歌地图Places API,需提前申请API密钥并处理请求鉴权
内容的提问来源于stack exchange,提问作者Ahmed Zaidan
相关产品推荐
相关产品推荐

