【问题标题】:MapKit show local results without location permissionMapKit 在没有位置许可的情况下显示本地结果
【发布时间】:2023-01-25 02:39:17
【问题描述】:

我正在构建一个类似 uber 的应用程序,它会在用户输入时显示推荐地址。最初,当我开始构建应用程序时,它会提示用户的位置,并且自动完成功能很智能,因为它会首先搜索本地地址。我意识到拥有用户的位置是不必要的,因为这更像是一种乘车请求服务,而不是实时服务。删除用户的位置后,自动完成变得非常差(预期)。这个应用程序将在一个非常特定的地区使用,我希望自动完成是智能的。有没有办法在不知道用户位置的情况下为 MKLocalSearch 设置区域?

这是检索自动完成地址的类...

import Foundation
import MapKit

class LocationSearchViewModel: NSObject, ObservableObject{
    
    @Published var totalPrice:String = "Loading..."

    @Published var results = [MKLocalSearchCompletion]()
    @Published var fromResult = MKLocalSearchCompletion()
    @Published var toResult = MKLocalSearchCompletion()
    
    @Published var fromAveLocation : AveLocation?
    @Published var toAveLocation : AveLocation?
    
    private let searchCompleter = MKLocalSearchCompleter()
        
    @Published var fromQueryFragment: String = ""{
        didSet{
            searchCompleter.queryFragment = fromQueryFragment
        }
    }
    
    @Published var toQueryFragment: String = ""{
        didSet{
            searchCompleter.queryFragment = toQueryFragment
        }
    }
    
    override init() {
        super.init()
        searchCompleter.delegate = self
        searchCompleter.queryFragment = fromQueryFragment
    }
    
    func selectLocation(_ localSearch: MKLocalSearchCompletion,_ localSearch2: MKLocalSearchCompletion){
        locationSearch(forLocalSearchCompletion: localSearch){response, error in
            self.locationSearch(forLocalSearchCompletion: localSearch2){response2, error2 in
                if let error = error{
                    print("DEBUG: Location search failed with error \(error.localizedDescription)")
                    return
                }
                
                if let error2 = error2{
                    print("DEBUG: Location search failed with error \(error2.localizedDescription)")
                    return
                }
                
                guard let item = response?.mapItems.first else{return}
                guard let item2 = response2?.mapItems.first else{return}
                let coordinate = item.placemark.coordinate
                let coordinate2 = item2.placemark.coordinate
                self.fromAveLocation = AveLocation(title: localSearch.title, subtitle: localSearch.subtitle, coordinate: coordinate)
                self.toAveLocation = AveLocation(title: localSearch2.title, subtitle: localSearch2.subtitle, coordinate: coordinate2)
                                
            }
        }
    }
    
    
    func locationSearch(forLocalSearchCompletion localSearch: MKLocalSearchCompletion,
                        completion: @escaping MKLocalSearch.CompletionHandler){
        let searchRequest = MKLocalSearch.Request()
        searchRequest.naturalLanguageQuery = localSearch.title.appending(localSearch.subtitle)
        let search = MKLocalSearch(request: searchRequest)
        
        search.start(completionHandler: completion)
    }
    
}


extension LocationSearchViewModel: MKLocalSearchCompleterDelegate{
    func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
        self.results = completer.results
    }
}

这是它被调用的地方......

ScrollView{
                VStack(alignment: .leading){
                    ForEach(viewModel.results, id: \.self){ result in
                        LocationSearchResultCell(title: result.title, subtitle: result.subtitle)
                            .onTapGesture {
                                
                                switch whereIsUser {
                                case .from:
                                    viewModel.fromQueryFragment = result.title
                                    viewModel.fromResult = result
                                    whereIsUser = .to
                                    focusedField = .to
                                    break
                                    
                                case .lookingFrom:
                                    viewModel.fromQueryFragment = result.title
                                    viewModel.fromResult = result
                                    whereIsUser = .to
                                    focusedField = .to
                                    break
                                
                                case .to:
                                    viewModel.toQueryFragment = result.title
                                    viewModel.toResult = result
                                    whereIsUser = .done
                                    withAnimation(.spring()){
                                        mapState = .locationSelected
                                        viewModel.selectLocation(viewModel.fromResult, viewModel.toResult)
                                    }

                                    break
                                    
                                case .lookingTo:
                                    viewModel.toQueryFragment = result.title
                                    viewModel.toResult = result
                                    whereIsUser = .done
                                    withAnimation(.spring()){
                                        mapState = .locationSelected
                                        viewModel.selectLocation(viewModel.fromResult, viewModel.toResult)
                                    }
                                    break
                                    
                                default:
                                    break
                                }
                            }
                    }
                }
            }

检查以确保模拟器位置设置在正确的位置。以防 MKLocalSearch 在没有获取用户位置的情况下工作。

【问题讨论】:

    标签: ios swift mapkit mkmapview


    【解决方案1】:

    您可以使用MKCoordinateRegion(center: CLLocationCoordinate2D, latitudinalMeters: CLLocationDistance, longitudinalMeters: CLLocationDistance) 手动创建区域

    searchRequest.region = MKCoordinateRegion(center: .init(latitude: /*region latitude*/, longitude: *region longitude*/), latitudinalMeters: 500, longitudinalMeters: 500)
    

    和/或

     searchCompleter.region = MKCoordinateRegion(center: .init(latitude: /*region latitude*/, longitude: *region longitude*/), latitudinalMeters: 500, longitudinalMeters: 500)
    

    【讨论】:

    • 我添加了代码,但它不起作用。我添加了这行代码... searchRequest.region = MKCoordinateRegion(center: .init(latitude: 26.3368, longitude: -81.4380), latitudinalMeters: 500, longitudinalMeters: 500)
    • @JohnCitrowske 您是否将评论区域更改为实际坐标?如果是这样,您也可以将仪表增加到更大的数量。这取决于地区本身。
    • 好的,问题是我是为搜索请求设置区域而不是搜索完成器。现在工作。太感谢了!
    • @JohnCitrowske 知道了,我将其添加到答案中。您介意单击绿色复选标记吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-10
    • 2017-07-30
    相关资源
    最近更新 更多