MKMapItem.openInMaps() 50% 的时间准确地显示地点标记

Posted

技术标签:

【中文标题】MKMapItem.openInMaps() 50% 的时间准确地显示地点标记【英文标题】:MKMapItem.openInMaps() displays place mark exactly 50% of the time 【发布时间】:2016-12-28 21:13:36 【问题描述】:

我发现运行一些代码以在地图视图 MKMapItem.openInMaps() 中显示位置仅在 50% 的时间内有效。 事实上,它恰好在 MKPlacemark 被显示和不被显示之间交替。

例如,每第 1、3、5、7...n 次代码运行一次,它就会显示地标,但每运行 2、4、6、8...m 次,地标不是显示出来。

运行下面发布的代码,这是 100% 可重现的。 这似乎是一个错误,但如果是这样,我很惊讶它之前没有被报告或修复。但考虑到失败正是在成功和失败之间交替出现,这让我认为还有其他事情发生,因此我在这里发帖看看是否有人熟悉这个问题,或者有什么应该做的事情缺失了从代码中,或者有一个解决方法:

override func viewDidAppear(_ animated: Bool) 
    displayMap()


func displayMap()

    let geoCoder = CLGeocoder()
    geoCoder.geocodeAddressString("1 Infinite Loop, Cupertino,California")  (placemark: [CLPlacemark]?, error: Error?) -> Void in
        if error == nil
        
            if let placemark = placemark, placemark.count > 0
            
                let location            = placemark.first
                let latitude            = (location?.location?.coordinate.latitude)!
                let longitude           = (location?.location?.coordinate.longitude)!
                let coordinates         = CLLocationCoordinate2DMake(latitude, longitude)

                let regionDistance:CLLocationDistance = 100000
                let regionSpan = MKCoordinateRegionMakeWithDistance(coordinates, regionDistance, regionDistance)

                let options = [
                    MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
                    MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
                ]
                let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
                let mapItem = MKMapItem(placemark: placemark)

                mapItem.name = "Apple"
                mapItem.phoneNumber = "(405) 123-4567"
                mapItem.openInMaps(launchOptions: options)
            
        
        else
        
            assert(false, "Unable to geocode")
        
    

这是代码运行第一次、第三次、第五次、第七次...时的结果

这是代码运行第二、四、六、八……次时的结果

注意失败截图中不仅地图上不显示地标,而且上滑也是空的。

(目前在 10.2 上观察到这一点,但在其他版本上也看到过)

【问题讨论】:

好的,所以我尝试了您的代码,问题在于,一旦您将位置居中并显示,如果您不关闭它并再次启动应用程序,它将不会显示它。因此,当您启动它并显示信息时,通过按 x 关闭 Map 应用程序内的弹出窗口并再次运行它,它将起作用......话虽如此,我不太确定究竟是什么导致了问题或如何摆脱它。 我注意到的另一件事是,如果地图应用程序中有任何其他先前的通知或位置放大,它仍然不会显示您的启动选项。我在应用程序中单击了我的位置,它显示了一个弹出窗口,我再次重新启动了应用程序,但它无法显示选项。所以,我认为这是一个错误。 @return0 感谢您的意见 【参考方案1】:

免责声明

是的,似乎mapItem.openInMaps 中存在一个错误,它将行车路线作为叠加层打开。

正如@return0准确描述的那样:

...我尝试了您的代码,问题在于,一旦您将位置居中并显示,如果您不关闭它并再次启动应用程序,它将不会显示...

更多奇事

    第二次,mapItem.openInMaps确实关闭行车路线叠加层(而不是显示新位置) 如果用户关闭所述叠加层,地图不再混乱(*)

(*) 这种情况的另一个奇怪之处在于,一旦覆盖层关闭,该位置就会消失。

错误? → 解决方法!

通过请求多个位置来强制路线覆盖消失。在实践中,这意味着调用两次相同位置的地图:

MKMapItem.openMaps(with: [mapItem, mapItem], launchOptions: options)

解决方法奖励

即使用户点击锚点并请求行驶方向,随后从您的应用程序调用地图到该位置或其他位置不会让它挂起。换句话说,它按预期工作。


完整的 Swift 3 源代码

func displayMap(_ address:String, name:String, tph:String)

    let geoCoder = CLGeocoder()
    geoCoder.geocodeAddressString(address)  (placemark: [CLPlacemark]?, error: Error?) -> Void in
        assert(nil == error,  "Unable to geocode \(error)")
        if error == nil
        
            if let placemark = placemark, placemark.count > 0
            
                let location            = placemark.first
                let latitude            = (location?.location?.coordinate.latitude)!
                let longitude           = (location?.location?.coordinate.longitude)!
                let coordinates         = CLLocationCoordinate2DMake(latitude, longitude)

                let regionDistance:CLLocationDistance = 10000
                let regionSpan = MKCoordinateRegionMakeWithDistance(coordinates, regionDistance, regionDistance)

                let options = [
                    MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
                    MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
                ]
                let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
                let mapItem = MKMapItem(placemark: placemark)

                mapItem.name = name
                mapItem.phoneNumber = tph
                MKMapItem.openMaps(with: [mapItem, mapItem], launchOptions: options)
             else 
                print("Something wrong with \(placemark)")
            
        
    

...和调用

@IBAction func doApple() 
    displayMap("1 Infinite Loop, Cupertino, California", name: "Apple", tph: "(408) 996–1010")


@IBAction func doMicrosoft() 
    displayMap("One Microsoft Way, Redmond, WA", name: "Microsoft", tph: "1-800-MICROSOFT")


@IBAction func doIBM() 
    displayMap("1 New Orchard Road. Armonk, New York", name: "IBM", tph: "(914) 499-1900")

【讨论】:

感谢您的回复 太棒了。你找到你的仓鼠了吗?这是一个相当有趣的难题,我相信当 Apple 修复该重新进入错误时,该解决方案仍然有效。 这似乎已在 ios 10.3 beta 3 中得到修复 干得好 SwiftArchitect(这对我的 obj-c 应用程序也有帮助)。我对 >= 10.0 和 【参考方案2】:

在 iOS 10.3.2 上,这个问题对我来说仍然存在。但是,此解决方法使 mapItem 不会消失:

MKMapItem.openMaps(with: [mapItem], launchOptions: options)

【讨论】:

以上是关于MKMapItem.openInMaps() 50% 的时间准确地显示地点标记的主要内容,如果未能解决你的问题,请参考以下文章

(第十周)Beta-2阶段成员贡献分

(第十三周)Final阶段成员贡献分

形状 (335476,50) 和 (3,50) 未对齐:50 (dim 1) != 3 (dim 0)

50 years, 50 colors

(第十二周)Debug阶段成员贡献分

名片打印系统