我正在尝试学习如何在 iOS 6 中的地图上放置图钉。我有一个可以编译和运行但显然会泄漏内存的代码——但是当我释放(或自动释放)mapData 对象时,我的应用程序崩溃了。错误是
0x1b7ac0
一个类的实例AddressAnnotation
被解除分配,而键值观察者仍向其注册。观察信息被泄露,甚至可能被错误地附加到其他对象上。在调试器中设置断点NSKVODeallocateBreak
以在此处停止。
有一篇关于这个错误的较早帖子,也是关于 MapKit:
在 NSKVODeallocateBreak 设置断点
但这对我没有帮助:
首先,我并不真正理解答案,而且似乎答案与我的问题无关,因为我没有以任何方式设置观察者(我知道,就是这样!)例如,在我的代码中没有任何地方有这些行
[addressAnnotation addObserver:self forKeyPath:kSelectedAnnotationObserverKeyPath options:NSKeyValueObservingOptionNew context:@"selectedOrDeselected"];
或任何其他远程类似的东西,这被认为是问题所在。
话虽如此,我还应该说我并不真正理解观察者的概念——我当然创建了一个自定义类MapData
,这是一个 NSObject <MKAnnotation>
我想这也可能是问题的根源。但我基本上是一头雾水。
我试图设置建议的符号断点,但这对我没有帮助:我看到我有一个BAD ACCESS
条件,但这就是我真正理解的全部!
我写的代码是这样的:
- (void) showRecordsOnMap
{
NSMutableArray *projectMapAnnotationsArray;
projectMapAnnotationsArray = [[NSMutableArray alloc] init];
int i = 0;
for (i = 0; i < [currentProject.recordArray count]; i++)
{
Record *record = [[[Record alloc] init]autorelease];
record = [currentProject.recordArray objectAtIndex:i];
CLLocationCoordinate2D newCoordinate;
newCoordinate.latitude = record.latitude;
newCoordinate.longitude = record.longitude;
int tag = 0;
NSString *title;
title = [[[NSString alloc] init] autorelease];
title = [NSString stringWithFormat:@"Record %d",record.record_ID];
NSString *subtitle;
subtitle = [[[NSString alloc] init] autorelease];
subtitle = [NSString stringWithFormat:@"Record %d",record.record_ID];
MapData *mapData =[[MapData alloc] initWithCoordinate:newCoordinate withTag:tag withTitle:title withSubtitle:title];
[projectMapAnnotationsArray addObject:mapData];
//[mapData release];
}
[projectMap addAnnotations:projectMapAnnotationsArray];
[projectMapAnnotationsArray release];
}
然后下一个需要的位
- (MKAnnotationView *) mapView:(MKMapView *)mapView
viewForAnnotation:(MapData *)annotation
{
static NSString *record = @"record";
//the result of the call is being cast (MKPinAnnotationView *) to the correct
//view class or else the compiler complains
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[projectMap
dequeueReusableAnnotationViewWithIdentifier:record];
if(annotationView == nil)
{
annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:record] autorelease];
}
//if((annotation).tag == 2) annotationView.pinColor = MKPinAnnotationColorRed;
//else annotationView.pinColor = MKPinAnnotationColorGreen;
annotationView.pinColor = MKPinAnnotationColorGreen;
//pin drops when it first appears
annotationView.animatesDrop=TRUE;
//tapping the pin produces a gray box which shows title and subtitle
annotationView.canShowCallout = YES;
return annotationView;
}
只要不释放 mapData 对象,此代码就会运行。但显然我需要释放它。作为另一个线索,如果我取消注释
// if((annotation).tag == 2) annotationView.pinColor = MKPinAnnotationColorRed;
// else annotationView.pinColor = MKPinAnnotationColorGreen;
我得到另一个错误:
[MKUserLocation 标签]:无法识别的选择器发送到实例 0x9fcb010 2013-05-22 23:05:13.726 Geo360[1175:c07] *** 由于未捕获的异常而终止应用程序
'NSInvalidArgumentException'
,原因:'-[MKUserLocation tag]:
无法识别的选择器发送到实例0x9fcb010
'
但在我看来,这第二个错误对我来说是一个更简单的愚蠢,我至少知道如何去寻找。但是错误“类AddressAnnotation
”让我完全迷失了。任何帮助是极大的赞赏!
编辑:
大家好——感谢您抽出宝贵时间提供帮助。我仍然很困惑。附件是 AnnaKarenina 建议的 MapData 对象的代码。Verbumdei 建议我将数组放在 ViewDidLoad 方法中作为一个强大的属性——我已经玩过了,但我也希望能够用一个可能有更多数据或更少数据的数组来刷新地图图钉,所以在我看来我每次都需要重新制作阵列。也许不是?AnnaKarenina 建议 MapData 中可能存在发布问题,现在我看到它有点怀疑我没有发布标签 - 但另一方面,这样做会产生警告!
再次感谢您的帮助...仍然没有解决。
地图数据.h:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
@interface MapData : NSObject <MKAnnotation>
{
NSString *_title;
NSString *subtitle;
NSUInteger tag;
CLLocationCoordinate2D _coordinate;
}
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
@property(nonatomic) NSUInteger tag;
// Getters and setters
- (id)initWithCoordinate:(CLLocationCoordinate2D)c withTag:(NSUInteger)t withTitle:(NSString *)tl withSubtitle:(NSString *)s;
@end
和MapData.m:
#import "MapData.h"
@implementation MapData
@synthesize coordinate;
@synthesize title;
@synthesize subtitle;
@synthesize tag;
-(id)initWithCoordinate:(CLLocationCoordinate2D)c withTag:(NSUInteger)t withTitle:(NSString *)tl withSubtitle: (NSString *)s
{
if(self = [super init])
{
coordinate = c;
tag = t;
title = tl;
subtitle = s;
}
return self;
}
- (void) dealloc
{
[title release];
[subtitle release];
[super dealloc];
}
@end