3

幸运的是,an 的标准标注视图MKAnnotationView满足了我们的需求 - titlesubtitleleftCalloutAccessoryViewrightCalloutAccessoryView.

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

MKAnnotationView 没有提供标准的方法来实现这一点。

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

4

2 回答 2

8

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

// 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
    }
  }
}
于 2015-12-01T13:25:10.000 回答
1

如果您只需要自定义字体,则需要子类MKAnnotationView化,但您不必重新创建使用标准免费获得的所有行为MKAnnotationView。这实际上很容易。

  1. 子类MKAnnotationView
  2. 覆盖 -layoutSubviews
  3. 选择an 时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]. 确保在您的地图首次加载时关闭断点,因为如上所述,MKAnnotationViews 在选择之前没有任何子视图。在进行选择之前,启用断点,点击您的引脚,断开并打印出视图树。你会UILabel在树的最底部看到一个。

于 2015-05-08T07:19:55.010 回答