Naver Map开发中调用asImage()转UIView为UIImage触发运行时错误
核心问题定位
使用SnapKit实现的AutoLayout自定义视图,在未完成布局计算的情况下直接调用渲染方法生成UIImage,会得到尺寸无效的空图片,传入NMFOverlayImage时就会触发运行时错误。
具体修复步骤
- 修复视图渲染前的布局逻辑
SnapKit实现的约束不会在赋值后立刻计算视图frame,此时自定义视图的bounds为.zero,必须先给视图指定确定的宽度(自适应高度的视图必须有明确宽度才能计算文本排版后的总高度),再调用layoutIfNeeded()强制所有子视图完成布局,才能拿到正确的视图尺寸。 - 替换可用的UIView转UIImage扩展
原有基于UIGraphicsImageRenderer的实现需要补充屏幕缩放适配、布局触发逻辑,直接使用以下实现即可:extension UIView { func asImage() -> UIImage { // 强制刷新布局,确保所有约束生效、子视图frame正确 layoutIfNeeded() let renderFormat = UIGraphicsImageRendererFormat.default() // 适配当前设备Retina屏幕缩放比,避免渲染出的图片模糊 renderFormat.scale = UIScreen.main.scale renderFormat.opaque = isOpaque let renderer = UIGraphicsImageRenderer(bounds: bounds, format: renderFormat) return renderer.image { renderContext in layer.render(in: renderContext.cgContext) } } } - 修正addMarker方法中的调用逻辑
初始化自定义视图、赋值文本后,必须先设置宽度约束、触发布局再渲染图片,参考实现:func addMarker(position: NMGLatLng, name: String, job: String, score: String) { // 初始化自定义标记视图 let customMarkerView = CustomInfoWindowView() // 赋值文本内容 customMarkerView.nameLabel.text = name customMarkerView.jobLabel.text = job customMarkerView.scoreLabel.text = score // 给视图设置固定宽度,按自身设计稿尺寸调整即可 customMarkerView.snp.makeConstraints { make in make.width.equalTo(280) } // 强制完成布局计算 customMarkerView.layoutIfNeeded() // 渲染为UIImage let markerIcon = customMarkerView.asImage() // 初始化地图标记 let marker = NMFMarker() marker.position = position marker.iconImage = NMFOverlayImage(image: markerIcon) marker.mapView = mapView }
额外注意事项
- 如果自定义视图包含圆角、阴影、边框等依赖layout的layer属性,不要在视图初始化方法里设置,要在
layoutSubviews里设置,否则渲染出的图片会出现效果丢失的问题。 - 单张标记图片尺寸不要超过1024*1024,过大会导致Naver Map SDK渲染标记时内存占用飙升触发崩溃。
内容的提问来源于stack exchange,提问作者장서영
相关产品推荐
相关产品推荐

