MKMapView 与 iOS 8 崩溃

Posted

技术标签:

【中文标题】MKMapView 与 iOS 8 崩溃【英文标题】:MKMapView with iOS 8 crash 【发布时间】:2015-05-22 08:16:09 【问题描述】:

我有一个简单的视图控制器,里面有一个 MKMapView 对象,以这种方式定义:

类声明:

@interface GeoViewController : UIViewController  <MKMapViewDelegate>

@property (nonatomic, strong) MKMapView* viewMap;

@end

实施:

@implementation GeoViewController

- viewDidAppear:(BOOL)animated  
    [super viewDidAppear:animated]; 
    viewMap = [[MKMapView alloc] init];
    MKCoordinateRegion worldRegion = MKCoordinateRegionForMapRect(MKMapRectWorld);
    [viewMap setRegion:worldRegion animated:YES];
    viewMap.pitchEnabled = YES;
    viewMap.showsUserLocation = YES;
    viewMap.delegate = self;
    [self.view addSubview:viewMap];


- (void)viewWillDisappear:(BOOL)animated 
    [super viewWillDisappear:animated];
    viewMap.showsUserLocation = NO;
    self.viewMap.delegate = nil;
    [self.viewMap removeFromSuperview];


- (void)resizeForOrientation:(BOOL)isLandscape withFrame:(CGRect)frame 
    [super resizeForOrientation:isLandscape withFrame:frame];
    const CGRect fullFrame = CGRectMake(0, 0, frame.size.width, frame.size.height);
    viewMap.frame = fullFrame;


@end

我第一次展示视图控制器的工作原理。然后我在我的应用程序中导航,如果我回到 GeoViewController,就会崩溃:

控制台上没有消息错误 main.m 已打开并报告“线程 1:EXC_BAD_ACCESS”

在调试导航器(左)我收到关于线程 1 的错误报告:

EAGLContext_renderbufferStorageFromDrawable(EAGLContext*, objc_selector*, unsigned int, id)

现在,谷歌搜索了很多,我找不到适合我的解决方案:

我也尝试过 viewDidDisappear,但没办法

 [EAGLContext setCurrentContext:nil];

这一行似乎崩溃了:

 viewMap.frame = fullFrame;

任何建议将不胜感激!

更新

我在测试中有时会收到其他错误:

检测到opengl线程冲突

【问题讨论】:

可能不相关,但由于viewMap 是一个属性,您应该使用self.viewMap = ... 分配它,而不仅仅是viewMap = ...。所以viewMap = [[MKMapView alloc] init]; 应该是self.viewMap = [[MKMapView alloc] init]; 【参考方案1】:

我在

中遇到 EXC_ARM_DA_ALIGN 错误
EAGLContext_renderbufferStorageFromDrawable(EAGLContext*, objc_selector*, unsigned int, id)

同样,在使用 MKMapView 时。

此问题中提到的解决方法:Adding google maps as subview crashes ios app with exc_bad 为我工作。

在我的目标方案中禁用“GPU 帧捕获”功能起到了作用。

【讨论】:

【参考方案2】:

产品 -> 编辑方案 -> 运行 -> 选项 -> 将 GPU 帧捕获设置为禁用。

Refetence Link

【讨论】:

【参考方案3】:

我认为是这条线导致了问题

[self.viewMap removeFromSuperview];

因为如果你说你刚刚导航回视图,viewDidLoad 就不会被再次调用。这就是为什么它说“线程 1:EXC_BAD_ACCESS”,因为您访问的是已发布的对象。它在 viewMap.frame = frame 上崩溃,因为您正在访问已释放的 viewMap 对象,因为您将其从其 superView 中删除。

【讨论】:

尝试 viewWillAppear:(BOOL)动画 或者您可以避免从其 superView 中删除 self.viewMap。由于你使用的是ARC,self.viewMap在不用的时候会自动释放。 我已经尝试过在 viewWillAppear 上移动和删除 viewWillDisappear 中的所有代码...在公海上航行! 你能给我这个项目的链接吗?我会尝试构建它。【参考方案4】:

viewDidAppear 在您按下控制器时调用,并且当它有另一个控制器按下时调用。因此,在您导航时,您正在删除地图。这同样适用于viewWillDisappear,因为它将在您将新控制器推到顶部以及最终弹出控制器时调用。

只需更改您的函数以在控制器首次出现时添加地图,并且仅在控制器从导航控制器中弹出时才执行删除。比如:

- viewDidAppear:(BOOL)animated  
    [super viewDidAppear:animated]; 

    if (self.isMovingToParentViewController)
      viewMap = [[MKMapView alloc] init];
      MKCoordinateRegion worldRegion = MKCoordinateRegionForMapRect(MKMapRectWorld);
      [viewMap setRegion:worldRegion animated:YES];
      viewMap.pitchEnabled = YES;
      viewMap.showsUserLocation = YES;
      viewMap.delegate = self;
      [self.view addSubview:viewMap];
  


- (void)viewWillDisappear:(BOOL)animated 
  [super viewWillDisappear:animated];

  // If being popped off, remove the map view. Otherwise
  // leave it alone as we need it when the user navigates
  // back
  if (self.isMovingFromParentViewController)
    viewMap.showsUserLocation = NO;
    self.viewMap.delegate = nil;
    [self.viewMap removeFromSuperview];
  

这可确保地图在控制器的生命周期内存在,这应确保对其的任何访问始终有效。

【讨论】:

@Velthune 我注意到您编辑了您的问题并将地图创建移动到viewDidAppear。您还应该在其周围放置一个防护装置,以便仅在首次按下控制器时创建。请参阅更新的答案。如果您一直添加/删除,则有一段时间您可能没有地图。因此,在第一次显示时创建它并在弹出时将其删除,如更新的答案所示。

以上是关于MKMapView 与 iOS 8 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何使 MKMap 适合指定的 View-Region?

MKMapView 在 iOS 6 上显示用户位置时崩溃

Mkmap查看用户位置

sigsegv segv_accerr 在 ios7 中崩溃 mkmapview

如何使用蓝点在我的 MKMapView 上显示我当前的位置和区域?

如何使 MKMapView 从顶部进入