MKAnnotationView标注的自定义字体

幸运的是, MKAnnotationView的标准callout视图符合我们的需求 – titlesubtitleleftCalloutAccessoryViewrightCalloutAccessoryView

不幸的是,我们在应用程序中使用自定义字体,并希望将这些自定义字体扩展到这些标注。

MKAnnotationView没有提供完成此任务的标准方法。

如何在MKAnnotation的标注视图中使用自定义字体?

因为我需要Swift版本 – 就在这里。 此外,您必须在didAddSubview()上调用setNeedsLayout(),否则当您取消选择并重新选择注释时,不会调用layoutSubviews()并且callout具有其旧字体。

 // elsewhere, in a category on UIView. // thanks to this answer: http://stackoverflow.com/a/25877372/607876 typealias ViewBlock = (_ view: UIView) -> Bool extension UIView { func loopViewHierarchy(block: ViewBlock?) { if block?(self) ?? true { for subview in subviews { subview.loopViewHierarchy(block: block) } } } } // then, in your MKAnnotationView subclass class CustomFontAnnotationView: MKAnnotationView { override func didAddSubview(_ subview: UIView) { if isSelected { setNeedsLayout() } } override func layoutSubviews() { // MKAnnotationViews only have subviews if they've been selected. // short-circuit if there's nothing to loop over if !isSelected { return } loopViewHierarchy { (view: UIView) -> Bool in if let label = view as? UILabel { label.font = labelFont return false } return true } } } 

如果你需要的只是一个自定义字体,你需要子类化MKAnnotationView ,但你不必重新创建使用标准MKAnnotationView免费获得的所有行为。 这实际上非常简单。

  1. 子类MKAnnotationView
  2. 覆盖-layoutSubviews
  3. 选择MKAnnotationView时, MKAnnotationView标注添加为子视图。 因此,我们可以递归循环遍历子类的子视图,并找到我们想要修改的UILabel
  4. 而已!

这种方法的唯一缺点是,如果您的字体小于或大于预期的标准系统字体,您可以看到标注调整它的大小。 如果在呈现给用户之前进行了所有调整,那就太棒了。

 // elsewhere, in a category on UIView. // thanks to this answer: http://stackoverflow.com/a/25877372/607876 // typedef void(^ViewBlock)(UIView *view, BOOL *stop); @interface UIView (Helpers) - (void)loopViewHierarchy:(ViewBlock)block; @end @implementation UIView (Helpers) - (void)loopViewHierarchy:(ViewBlock)block { BOOL stop = false; if (block) { block(self, &stop); } if (!stop) { for (UIView* subview in self.subviews) { [subview loopViewHierarchy:block]; } } } @end // then, in your MKAnnotationView subclass // @implementation CustomFontAnnotationView - (void)layoutSubviews { // MKAnnotationViews only have subviews if they've been selected. // short-circuit if there's nothing to loop over if (!self.selected) { return; } [self loopViewHierarchy:^(UIView *view, BOOL *stop) { if ([view isKindOfClass:[UILabel class]]) { *stop = true; ((UILabel *)view).font = {custom_font_name}; } }]; } @end 

我通过首先创建我的MKAnnotationView子类并在我的重写-layoutSubviews设置断点来检查视图树。 在调试器中,我然后发出了po [self recursiveDescription] 。 确保在地图首次加载时关闭断点,因为如上所述, MKAnnotationView在选择之前没有任何子视图。 在进行选择之前,启用断点,点击引脚,中断并打印视图树。 你会在树的最底部看到一个UILabel