Ios 通过从属性列表读取的NSDictionary进行循环会带来麻烦
嘿,伙计们,我在读这样一篇文章: 如您所见,它是一个plist,包含不同类型的注释信息(C,Visitor)。我可以很好地显示每个注释类型,但我正在尝试循环所有类型,并在地图视图上同时显示所有注释。代码如下:Ios 通过从属性列表读取的NSDictionary进行循环会带来麻烦,ios,annotations,mkmapview,property-list,Ios,Annotations,Mkmapview,Property List,嘿,伙计们,我在读这样一篇文章: 如您所见,它是一个plist,包含不同类型的注释信息(C,Visitor)。我可以很好地显示每个注释类型,但我正在尝试循环所有类型,并在地图视图上同时显示所有注释。代码如下: NSLog(@"loadAnnotations"); NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"PermitData" ofType:@"plist"]; NSDictionary *rootOfPerm
NSLog(@"loadAnnotations");
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"PermitData" ofType:@"plist"];
NSDictionary *rootOfPermitDataPlistDict = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
// NSMutableDictionary *permitDict = [[NSMutableDictionary alloc] init];
if ([self title] == @"All Permits") {
for (id key in rootOfPermitDataPlistDict) {
NSLog(@"key:%@",key);
//[key retain];
NSMutableDictionary *permitDict = [NSDictionary dictionaryWithDictionary:[rootOfPermitDataPlistDict objectForKey:key]];
//[key release];
//array containing annotation information: latitude, longitude, title, subtitle(see PermitData.plist)
NSArray *annotationsArray = [[NSArray alloc] initWithArray:[permitDict objectForKey:@"annotations"]];
[permitDict release];
[rootOfPermitDataPlistDict release];
CLLocationCoordinate2D workingCoordinate;
NSDictionary *annotationContainerDict = [[NSDictionary alloc] init];
//loop through annotations array, creating parking annotations filled with the information found in the plist
for(annotationContainerDict in annotationsArray){
NSLog(@"%@",annotationContainerDict);
ParkingAnnotation *parkingAnnot = [[ParkingAnnotation alloc] init];
workingCoordinate.latitude = [[annotationContainerDict objectForKey:@"latitude"] doubleValue];
workingCoordinate.longitude = [[annotationContainerDict objectForKey:@"longitude"] doubleValue];
[parkingAnnot setCoordinate:workingCoordinate];
[parkingAnnot setTitle:[annotationContainerDict objectForKey:@"title"]];
[parkingAnnot setSubtitle:[annotationContainerDict objectForKey:@"subtitle"]];
if ([parkingAnnot title] == @"C Parking") [parkingAnnot setAnnotationType:annotationTypeC];
else if ([parkingAnnot title] == @"Visitor Parking") [parkingAnnot setAnnotationType:annotationTypeVisitor];
[mapView addAnnotation:parkingAnnot];
[parkingAnnot release];
}
[permitDict release];
}
}
这是我运行程序时的控制台输出:
2010-11-25 03:25:28.020 Parking[38918:207] All Permits
2010-11-25 03:25:28.021 Parking[38918:207] loadAnnotations
2010-11-25 03:25:28.021 Parking[38918:207] key:C
2010-11-25 03:25:28.021 Parking[38918:207] {
latitude = "38.545301";
longitude = "-121.754066";
subtitle = "VP 17";
title = "C Parking";
}
2010-11-25 03:25:28.022 Parking[38918:207] {
latitude = "38.544831";
longitude = "-121.754785";
subtitle = "VP 16";
title = "C Parking";
}
2010-11-25 03:25:28.022 Parking[38918:207] {
latitude = "38.544781";
longitude = "-121.755729";
subtitle = "VP 22";
title = "C Parking";
}
2010-11-25 03:25:28.022 Parking[38918:207] {
latitude = "38.544412";
longitude = "-121.752489";
subtitle = "VP 15";
title = "C Parking";
}
因此,它正确地循环第一个NSDictionary,但在即将开始循环下一个NSDictionary时崩溃。我尝试将NSDictionary更改为NSMutableDictionary,但结果是一样的。因此,当我在表视图中选择“allallows”行时,它会挂起几分之一秒(不切换到map视图),然后崩溃,不会产生错误
如果有人不介意在这里帮助我,我将不胜感激。提前谢谢
编辑:
以下是堆栈跟踪(在下面的注释中描述):
2010-11-25 20:28:08.141停车许可证
2010-11-25 20:28:08.142停车场[39400:207]负荷注释
2010-11-25 20:28:08.142停车键:C
2010-11-25 20:28:08.143停车场[39400:207]{
纬度=“38.545301”;
经度=“-121.754066”;
副标题=“VP 17”;
title=“C停车场”;
}
2010-11-25 20:28:08.143停车场[39400:207]{
纬度=“38.544831”;
经度=“-121.754785”;
副标题=“VP 16”;
title=“C停车场”;
}
2010-11-25 20:28:08.143停车场[39400:207]{
纬度=“38.544781”;
经度=“-121.755729”;
副标题=“VP 22”;
title=“C停车场”;
}
2010-11-25 20:28:08.144停车场[39400:207]{
纬度=“38.544412”;
经度=“-121.752489”;
副标题=“VP 15”;
title=“C停车场”;
}
2010-11-25 20:28:08.145停止[39400:207]***由于未捕获的异常“NSGenericeException”而终止应用程序,原因:“***集合在枚举时发生了变异。{type=mutable dict,count=1,
条目=>
0 : =
}
'
***第一次抛出时调用堆栈:
(
0 CoreFoundation 0x025fdb99例外预处理+185
1 libobjc.A.dylib 0x0274d40e objc_异常_抛出+47
2 CoreFoundation 0x025fd659 uunsuFastEnumerationMutationHandler+377
3停车0x00002e93-[ParkingMapViewController加载注释]+364
4停车0x00002caf-[ParkingMapViewController viewDidLoad]+117
5 UIKit 0x0036a5ca-[UIViewController视图]+179
6 UIKit 0x003689f4-[UIViewController contentScrollView]+42
7 UIKit 0x003787e2-[UINavigationController _计算机和应用程序克隆内容插入DeltaForviewController:+48
8 UIKit 0x00376ea3-[UINavigationController\u layoutViewController:+43
9 UIKit 0x00378067-[UINavigationController\u开始转换:从ViewController:toViewController:+326
10 UIKit 0x00372ccd-[UINavigationController _STARTDEFERREEDTRANSION(如果需要)]+266
11 UIKit 0x00379d8b-[UINavigationController推送视图控制器:转换:强制立即:+876
12 UIKit 0x00372b67-[UINavigationController推送视图控制器:动画::+62
13停车0x00002914-[PermitListViewController表视图:didSelectRowAtIndexPath:+307
14 UIKit 0x00333a48-[UITableView\u selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:+1140
15 UIKit 0x0032a32e-[UITableView\u用户选择行索引路径:+219
16基金会0x000 03F21A
17 CoreFoundation 0x025def73\uuuu CFRUNLOOP\u正在调用\u OUT\u到\u计时器\u回调函数\uuuu+19
18芯基础0x025e05b4 uu CFRunLoopDoTimer+1364
19 CoreFoundation 0x0253cdd9_u CFRunLoopRun+1817
20 CoreFoundation 0x0253c350 CFRUNLOOPSCRONE+208
21 CoreFoundation 0x0253c271 CFRUNLOOPSRUNINMODE+97
22图形服务0x02edc00c GSEventRunModal+217
23图形服务0x02edc0d1 GSEventRun+115
24 UIKit 0x002ceaf2 UIApplicationMain+1160
25停车位0x00001e08主+102
26停车0x00001d99启动+53
)
在抛出“NSException”实例后调用terminate
但是,我正在for循环中释放permitdct(第二个[permitdct release]没有注释),所以我不知道为什么它会抱怨NSDictionary是不可变的。如您所见,PermitDisct的类型为NSMutableDictionary,因此我不知道它为什么会给我这个错误。代码崩溃有两个主要原因 首先,该行位于for循环内:
[rootOfPermitDataPlistDict release];
销毁当前正在循环的对象。将其移到最末端--if([self title]…
语句的右括号之后
第二行,这两行表示:
[permitDict release];
应删除。不要释放PermitDisct,因为您正在使用dictionaryWithDictionary创建它,该dictionaryWithDictionary返回自动删除的对象
有了这两个更改,代码应该可以运行了。
然而还有一些其他问题:
- 您可以alloc+init
但从不释放它(内存泄漏)。在通过该数组的for循环之后释放它(您当前有第二个annotationsArray
)[permitDict release];
- 你可以使用alloc+init
[permitDict release];
NSString * const PPAnnotationsKey = @"annotations"; NSString * const PPTitleKey = @"title"; NSString * const PPSubtitleKey = @"subtitle"; NSString * const PPLatitudeKey = @"latitude"; NSString * const PPLongitudeKey = @"longitude"; NSLog(@"loadAnnotations"); NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"PermitData" ofType:@"plist"]; // autoreleased NSDictionary *permitDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath]; // autoreleased if ([[self title] isEqualToString:@"All Permits"]) { for (NSString *parkingGroup in permitDictionary) { NSLog(@"parkingGroup == %@", parkingGroup); NSArray *annotations = [parkingGroup objectForKey:PPAnnotationsKey]; for (NSDictionary *entry in annotations) { PPParkingAnnotation *annotation = [PPParkingAnnotation parkingAnnotationWithDictionary:entry]; // autoreleased if (annotation) { // assuming here that mapView's addAnnotation: will retain the // annotation [mapView addAnnotation:annotation]; } } } } @interface PPParkingAnnotation : NSObject <MKAnnotation> { CLLocationCoordinate2D coordinate; NSString *title; NSString *subtitle; } + (id)parkingAnnotationWithDictionary:(NSDictionary *)dictionary; - (id)initWithDictionary:(NSDictionary *)dictionary; @properties... @end @implementation PPParkingAnnotation + (id)parkingAnnotationWithDictionary:(NSDictionary *)dictionary { return [[[[self class] alloc] initWithDictionary:dictionary] autorelease]; } - (id)initWithDictionary:(NSDictionary *)dictionary { [self setTitle:[dictionary objectForKey:PPTitleKey]]; [self setSubtitle:[dictionary objectForKey:PPTitleKey]]; // and so on. }