2011-09-13 47 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