2011-09-13 37 views
1

我有一个使用谷歌地图视图的应用程序。
在这个应用程序中,我想显示一些自定义的切片和userLocation的自定义视图。当位置管理器给出一个标题时,我想要显示userLocation的自定义视图,如果它未能提供一个,我想要默认的蓝色动画点回来等等...iPhone - 需要一些EXC_BAD_ACCESS帮助我疯狂(包括完整的源代码)

可用的项目和源代码HERE

嗯,有2个问题在这里:

1日的问题,真正的坏。你可以用这个小应用程序玩几个小时。但是......启动它,等待它加载,将其发送到后台,将iPhone置于睡眠模式,等待一分钟,唤醒iPhone,启动应用程序(唤醒它):崩溃,EXC_BAD_ACCESS。做同样的事情不要把iPhone置于睡眠模式:不要崩溃。不等待一分钟,但几秒钟,没有崩溃。 10秒,没有撞车,20秒,没有撞车,接近30秒,也许是碰撞,接近一分钟,撞车!

第二个问题(奖金:-)),可以与第一个链接,但这不是真正的这个问题的核心:我用来实现userPinLocation更新从/到蓝色引脚似乎有一个非常糟糕的副作用:当你在街道上移动时,userLocation不会在地图上移动。对于第二个问题的任何答案,如果它没有直接与崩溃链接,请使用评论而不是答案。这不是问题的核心......我想...

要找到错误的代码,我已经减少了我的应用程序的最低限度。这给了下面的代码(一些提示,在源代码注释):

EXC_BAD_ACCESS_TestViewController.h

#import <MapKit/MapKit.h> 

@interface EXC_BAD_ACCESS_TestViewController : UIViewController<CLLocationManagerDelegate> { 

    CLLocationManager* locationMgr; 
    NSMutableArray* customAnnotations; 
    CLLocationDirection userHeading; 
    MKMapView* myMapView; 
} 

@property(nonatomic, retain) CLLocationManager* locationMgr; 
@property(nonatomic, retain) NSMutableArray* customAnnotations; 
@property(nonatomic, assign) CLLocationDirection userHeading; 
@property(nonatomic, retain) IBOutlet MKMapView* myMapView; 

- (void) loadAnnotations; 

@end 

EXC_BAD_ACCESS_TestViewController.m

// On first launch, due to code simplification, the app may crash when asked authorization to use geo hardware. Just kill/relaunch after accepting. 
// Breakpoints on each method entry : EXC_BAD_ACCESS crash without any break-stop 

#import "EXC_BAD_ACCESS_TestViewController.h" 
#import "CustomAnnotation.h" 

@implementation EXC_BAD_ACCESS_TestViewController 

@synthesize locationMgr, customAnnotations, myMapView, userHeading; 

// =========================================================================================================== 
-(id) initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super initWithCoder:aDecoder]; 
    if (!self) return nil; 

    self.userHeading = -1; 

    return self; 
} 

// =========================================================================================================== 
- (void) viewDidLoad 
{ 
    [self loadAnnotations]; 

    self.myMapView.mapType = MKMapTypeStandard; 
    self.myMapView.showsUserLocation = YES; 

    // ----------------------------------------------- 
    // Just comment this sole line : no more crash 
    // ----------------------------------------------- 
    for (CustomAnnotation* pin in self.customAnnotations) [self.myMapView addAnnotation:pin]; 

    // locationManager 
    self.locationMgr = [[CLLocationManager alloc] init]; 
    self.locationMgr.desiredAccuracy = kCLLocationAccuracyBest; 
    self.locationMgr.distanceFilter = 1.0; 
    self.locationMgr.headingFilter = 1.0; 
    self.locationMgr.purpose = @"Some purpose."; 
    self.locationMgr.delegate = self; 
    [self.locationMgr startUpdatingHeading]; 

    [super viewDidLoad]; 
} 

// =========================================================================================================== 
- (void) loadAnnotations 
{ 
    // Code for testing, real code gets the datas using another way of doing, as simple as this one 
    self.customAnnotations = [NSMutableArray array]; 
    double latitude = 45.0; 
    double longitude = -45.0; 

    for (int i=1; i<=400; i++) { 
     CLLocationCoordinate2D pinLocation = CLLocationCoordinate2DMake(latitude, longitude); 
     CustomAnnotation* pin = [[[CustomAnnotation alloc] initWithCoordinate:pinLocation] autorelease];    
     [self.customAnnotations addObject:pin]; 

     latitude += 0.01; 
     longitude += 0.01; 
    } 
} 

// =========================================================================================================== 
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation 
{ 
    MKAnnotationView* pinView = nil; 
    NSString* annotationIdentifier; 
    UIImage* pinImage; 
    BOOL canShowCallout; 

    // User location 
    if ([annotation isKindOfClass:[MKUserLocation class]] && self.userHeading >= 0) { 
     annotationIdentifier = @"UserLocationAnnotation"; 
     pinImage = [UIImage imageNamed:@"custom_userlocation.png"]; 
     canShowCallout = NO; 
    } 
    // Custom Pin 
    else if ([annotation isKindOfClass:[CustomAnnotation class]]) { 
     annotationIdentifier = @"CustomAnnotation"; 
     pinImage = [UIImage imageNamed:@"custom_pin.png"]; 
     canShowCallout = YES; 
    } 
    // Others 
    else { 
     return nil; 
    } 

    pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier]; 

    if (pinView) { 
     pinView.annotation = annotation; 
    } 
    else { 
     pinView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier] autorelease]; 
     if (pinView) { 
      pinView.image = pinImage; 
      pinView.canShowCallout = canShowCallout; 

      if (canShowCallout) { 
       pinView.calloutOffset = CGPointMake(-5, 5); 
       pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
      } 
     } 
    } 

    return pinView; 
} 

// ----------------------------------------------- 
// Just comment this method : no more crash 
// ----------------------------------------------- 
// =========================================================================================================== 
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading 
{ 
    if (!self.myMapView) return; 
    if (!self.myMapView.userLocation) return; 

    CLLocationDirection compassHeading_True = newHeading.trueHeading; 
    CLLocationDirection compassHeading_Magnetic = newHeading.magneticHeading; 

    CLLocationDirection heading; 
    if (compassHeading_True == -1)    heading = compassHeading_Magnetic; 
    else if (newHeading.headingAccuracy >= 0) heading = compassHeading_True; 
    else          heading = -1; 

    // If we get/loose the heading, update pin image 
    // I didn't found any other solution to force the user pin to update its display. 
    if ((self.userHeading == -1 || heading == -1) && self.userHeading != heading) { 
     [self.myMapView removeAnnotation:self.myMapView.userLocation]; 
     self.userHeading = heading; 
     [self.myMapView addAnnotation:self.myMapView.userLocation]; 
    } 

    self.userHeading = heading; 

    // ------------------------------------ 
    // Some non bugued code was there 
    // ------------------------------------ 
} 

// =========================================================================================================== 
- (void) dealloc 
{ 
    self.myMapView = nil; 
    self.customAnnotations = nil; 
    self.locationMgr = nil; 

    [super dealloc]; 
} 

@end 

CustomAnnotation.h

#import <MapKit/MapKit.h> 

@interface CustomAnnotation : NSObject<MKAnnotation> { 
    CLLocationCoordinate2D coordinate; 
} 

@property(nonatomic, assign) CLLocationCoordinate2D coordinate; 

- (id)initWithCoordinate:(CLLocationCoordinate2D) c; 
@end 

CustomAnnotation.m

#import "CustomAnnotation.h" 

@implementation CustomAnnotation 

@synthesize coordinate; 

// =========================================================================================================== 
- (id)initWithCoordinate:(CLLocationCoordinate2D) c 
{ 
    self = [super init]; 
    if (!self) return nil; 

    self.coordinate = c; 

    return self; 
} 

// =========================================================================================================== 
- (NSString*)subtitle 
{ 
    return @""; 
} 

// =========================================================================================================== 
- (NSString*)title 
{ 
    return @""; 
} 

@end 

我试图断点在每个方法,努力实现与环境变量僵尸(但是这需要在设备上跑了,我不知道他们已经真正激活),没有任何解决方案启动......我仍然不知道发生了什么问题。

您是否看到如何解决EXC_BAD_ACCESS问题?
对于第二个问题的任何答案,如果它没有解决崩溃,请使用注释而不是答案。就我所见,这个问题并不是问题的核心。

提示:我在上面的代码中发现了2条评论,我发现了一些解决方案的开始。有两个地方,似乎没有连接,可以从代码中解决问题。什么让我发疯是OR。

在iPhone 4上运行ios 4.2。1

+0

你能为我们创造微小的应用程序,并把它上传到mediafire.com或其他一些网站在这里发表的URL,所以我们可以把它捡起来。太懒惰地创建一个项目并复制粘贴代码以进行调试。 – ARC

+0

@Nikita:OK,做,看到我的编辑 – Oliver

+1

[self.myMapView removeAnnotation:self.myMapView.userLocation]。 //这一行导致stacktrace崩溃,这是我见过的.. – ARC

回答

1
[self.myMapView removeAnnotation:self.myMapView.userLocation]; 

这条线是造成从堆栈跟踪崩溃,这是我所看到的。

当我看到EXC_BAD_ACCESS我确实在gdb一个BT。我已经添加了Guard Malloc断点。看看它说的关于删除注释的堆栈。

+0

你能否详细介绍一下“gdb中的bt,我已经添加了Guard Malloc断点。” ?什么是bt?你是如何设置Guard malloc bp的? – Oliver

+1

BT正在回溯Trace。 XCode - > Goto Run - > Show - > Breakpoints(Alt-Command-B),滚动到列表底部并添加符号malloc_error_break – ARC

+0

我这样做了,但是如果没有定义断点,它也完全一样。你能不能给更多的读者提供一些细节(截图)给你的答案?您定义的BP,以及显示错误的堆栈跟踪。请 ? – Oliver

0

你可以尝试重写一个在您的视图控制器.m文件名为didReceiveMemoryWarning方法。

有时会发生什么情况是,在装置上存储器得到低,由于正在运行的应用和IOS将消息发送到该应用。现在的问题是,当你不重写内存警告方法,它的默认行为是从内存中删除任何subview S的不可见。当您的应用程序运行时,这可能导致僵尸变量。

时退房apple doc

+0

不是我想的问题,它在真实应用程序中被覆盖。你测试了吗? – Oliver