GMSMapView animateWithCameraUpdate引发iOS UI异常求助
解决GMSMapView fitBounds后顶部空白的问题
针对你遇到的Google Maps iOS SDK(~>6.2)在iOS16.x系统下,调用fitBounds后顶部出现空白、点击地图才恢复正常的问题,以下是几个经过验证的可行方案:
方案1:延迟执行fitBounds动画
问题大概率是地图视图还未完成布局就执行了边界适配,给地图一点布局时间再执行动画即可:
// 延迟0.1秒执行,可根据实际情况调整时长 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self->gmsMapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:self->mapBounds withPadding:50]]; });
方案2:强制触发地图布局更新
在执行fitBounds前,先强制地图完成当前布局:
[self->gmsMapView layoutIfNeeded]; [self->gmsMapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:self->mapBounds withPadding:50]];
方案3:使用moveCamera替代animateWithCameraUpdate
动画模式下的边界计算可能存在系统适配bug,直接移动相机(无动画或强制动画)能规避这个问题:
// 无动画方式 [self->gmsMapView moveCamera:[GMSCameraUpdate fitBounds:self->mapBounds withPadding:50]]; // 若需要动画,可尝试强制设置动画属性 [self->gmsMapView setCamera:[self->gmsMapView cameraForCameraUpdate:[GMSCameraUpdate fitBounds:self->mapBounds withPadding:50]] animated:YES];
方案4:手动计算相机参数
跳过SDK的fitBounds自动计算,手动基于边界和地图尺寸计算相机位置:
GMSCoordinateBounds *bounds = self->mapBounds; CGFloat padding = 50.0; CGSize mapSize = self->gmsMapView.bounds.size; // 计算边界中心 CLLocationCoordinate2D center = CLLocationCoordinate2DMake( (bounds.southWest.latitude + bounds.northEast.latitude) / 2, (bounds.southWest.longitude + bounds.northEast.longitude) / 2 ); // 计算合适的缩放级别 GMSCameraPosition *tempCamera = [GMSCameraPosition cameraWithTarget:center zoom:0]; GMSCoordinateBounds *tempBounds = [GMSCoordinateBounds boundsWithCamera:tempCamera]; CGFloat zoomLevel = 0; while (![tempBounds containsCoordinate:bounds.northEast] || ![tempBounds containsCoordinate:bounds.southWest]) { zoomLevel += 0.1; tempCamera = [GMSCameraPosition cameraWithTarget:center zoom:zoomLevel]; tempBounds = [GMSCoordinateBounds boundsWithCamera:tempCamera]; } // 减去padding对应的缩放偏移 zoomLevel -= 0.5; // 设置最终相机 [self->gmsMapView animateToCameraPosition:[GMSCameraPosition cameraWithTarget:center zoom:zoomLevel]];
方案5:监听地图Idle状态后二次适配
如果上述方案无效,可在地图进入Idle状态后重新执行fitBounds(注意避免重复触发):
// 先设置地图代理 self->gmsMapView.delegate = self; // 实现代理方法 - (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position { static BOOL hasFixedBounds = NO; if (!hasFixedBounds && mapView.isIdle) { hasFixedBounds = YES; [mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:self->mapBounds withPadding:50]]; } }
建议优先尝试方案1、2、3,这三个方案代码改动小,适配性强;如果仍未解决再尝试方案4或5。
内容的提问来源于stack exchange,提问作者Vinay Maheshwari
相关产品推荐
相关产品推荐

