2017-02-11 48 views

回答

2

自我回答在這裏,因爲我花了瘋狂的時間纔得到這個權利,並認爲別人可能需要這個。當時我需要開發這個功能,幾乎沒有任何關於創建定製轉子細節的例子,而Apple的文檔非常稀少。我終於明白了,在看完和關注之後(並在代碼的屏幕上暫停)WWDC Session 202(從24:17開始)。

我需要弄清楚的最棘手的事情是如何可靠地返回UIAccessibilityCustomRotorItemResult。對於MKMapView,您想要返回MKAnnotationView s,但註釋並不保證具有關聯的視圖(它們會被回收,如果註釋是屏幕外的,它很可能重用視圖),所以我第一次嘗試一直留下一些或大部分我的註釋。

神奇的是在動畫設置:屬性設置爲false:

self.mapView.setCenter(requestedAnnotation.coordinate, animated: false) 

不能使用視圖(:MKAnnotation)由於上述原因,還等什麼上面的行代碼的移動地圖所以你的針是在中心。因爲它不具有動畫效果,註釋會立即創建視圖,在下一行代碼中,在我的測試中,它將保證返回MKAnnotationView

YVVM,但請隨時添加改進建議,因爲我覺得以這種方式導航地圖對於VoiceOver用戶至關重要。

func configureCustomRotors() { 
    let favoritesRotor = UIAccessibilityCustomRotor(name: "Bridges") { predicate in 
    let forward = (predicate.searchDirection == .next) 

    // which element is currently highlighted 
    let currentAnnotationView = predicate.currentItem.targetElement as? MKPinAnnotationView 
    let currentAnnotation = (currentAnnotationView?.annotation as? BridgeAnnotation) 

    // easy reference to all possible annotations 
    let allAnnotations = self.mapView.annotations.filter { $0 is BridgeAnnotation } 

    // we'll start our index either 1 less or 1 more, so we enter at either 0 or last element 
    var currentIndex = forward ? -1 : allAnnotations.count 

    // set our index to currentAnnotation's index if we can find it in allAnnotations 
    if let currentAnnotation = currentAnnotation { 
     if let index = allAnnotations.index(where: { (annotation) -> Bool in 
     return (annotation.coordinate.latitude == currentAnnotation.coordinate.latitude) && 
    (annotation.coordinate.longitude == currentAnnotation.coordinate.longitude) 
     }) { 
      currentIndex = index 
     } 
    } 

    // now that we have our currentIndex, here's a helper to give us the next element 
    // the user is requesting 
    let nextIndex = {(index:Int) -> Int in forward ? index + 1 : index - 1} 

    currentIndex = nextIndex(currentIndex) 

    while currentIndex >= 0 && currentIndex < allAnnotations.count { 
     let requestedAnnotation = allAnnotations[currentIndex] 

     // i can't stress how important it is to have animated set to false. save yourself the 10 hours i burnt, and just go with it. if you set it to true, the map starts moving to the annotation, but there's no guarantee the annotation has an associated view yet, because it could still be animating. in which case the line below this one will be nil, and you'll have a whole bunch of annotations that can't be navigated to 
     self.mapView.setCenter(requestedAnnotation.coordinate, animated: false) 
     if let annotationView = self.mapView.view(for: requestedAnnotation) { 
     return UIAccessibilityCustomRotorItemResult(targetElement: annotationView, targetRange: nil) 
     } 

     currentIndex = nextIndex(currentIndex) 
    } 

    return nil 
    } 

    self.accessibilityCustomRotors = [favoritesRotor] 
}