类初始化破坏应用程序

时间:2010-10-29 14:43:57

标签: iphone objective-c cocoa-touch xcode

我最近为我的iPhone应用程序创建了一个新类,它将保存从包含街道地址和感兴趣点的GPS点的文本文件中读取的信息。

问题是,无论何时我添加代码来初始化类,我的应用程序都会加载并立即退出,控制台中没有错误。当我删除它,一切都很好。我根本看不出代码有什么问题。

这是构造函数:

#import "GPSCoordinate.h"


@implementation GPSCoordinate
-(GPSCoordinate*) initWithData:(NSString *)rawData size:(int)size
{
self = [super init];
location = [NSMutableArray arrayWithCapacity:size];
coordinates = [NSMutableArray arrayWithCapacity:(int)size];

NSArray *tokens = [rawData componentsSeparatedByString:@"@"];

for (int i = 0; i < size - 1; i++) {
    //Sub tokens
    NSString *line = [tokens objectAtIndex:i];
    NSArray *lineTokens = [line componentsSeparatedByString:@":"];
    //Store address
    [location addObject:[lineTokens objectAtIndex:0]];
    //Store GPS coords
    NSString *coords = [lineTokens objectAtIndex:1];
    coords = [[coords stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""] 
              stringByReplacingCharactersInRange:NSMakeRange([coords length]-2, 1) withString:@""];
    NSArray *coordsTokens = [coords componentsSeparatedByString:@" "];
    CLLocationCoordinate2D coord;
    coord.latitude = [[coordsTokens objectAtIndex:0] doubleValue];
    coord.longitude =[[coordsTokens objectAtIndex:1] doubleValue];
    [coordinates addObject:coords];
    [line release];
    [lineTokens release];
    [coords release];
    [coordsTokens release];
}

return self;
}

@end

以下是我在另一个课程中对其进行的调用:

self.gps = [[GPSCoordinate alloc] initWithData:gpsRawData size:[[gpsRawData componentsSeparatedByString:@"@"] count]];

我在哪里错了?

2 个答案:

答案 0 :(得分:6)

我看到了很多问题。

  • 您没有检查[super init]的返回值。
  • 您将自动释放的数组存储在大概是ivars(位置和坐标)中。
  • 您正在传递一个单独的大小参数,该参数是从调用之外的rawData计算的,但是-initWithData:在方法内进行完全相同的计算。 size:参数在这里看起来完全是多余的。
  • 您正在完全跳过最后一个令牌。你应该把它换成循环并简单地使条件i < size。或者,如果您的目标是iOS 4.0或更高版本,则可以将整个循环转换为

    [tokens enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
        NSString *line = obj;
        // rest of loop body
    }];
    

    由于您似乎不需要循环内的索引,您也可以只使用for-in循环(这适用于4.0之前的iOS设备):

    for (NSString *line in tokens) {
        // body of loop
    }
    
  • 您没有检查您的数据是否有效。如果某行包含“foo”,则程序在尝试访问[lineTokens objectAtIndex:1]时会崩溃。类似地,如果你有字符串“foo:”,它会崩溃,因为它试图删除coordinates变量的第一个字符。实际上,冒号后的任何小于2个字符都会崩溃。如果冒号后面没有空格,它也会崩溃。

  • 最后,最后对-release的所有调用都会崩溃。所有这四个对象都是自动释放的对象,因此现在通过调用-release来确保应用程序在自动释放池耗尽时崩溃。
  • 您还在coords数组中存储coordinates(例如字符串)。大概你打算存储coord,虽然你需要将它包装在NSValue中以便将它存储在NSArray中。

答案 1 :(得分:2)

我看到了几个问题。

1)最根本的是,你发布了许多你没有分配的对象。例如:

NSString *line = [tokens objectAtIndex:i];
....
[line release];

不正确。查看Cocoa Memory Management Rules

2)你为什么要[[gpsRawData componentsSeparatedByString:@"@"] count传递大小 当您需要在方法中重复initWithData:size:调用时,您的-componentsSeparatedByString:方法。传递一个单独的“大小”并没有获得任何东西,涉及输入的冗余解析,并打开更多可能的错误(如果调用者传入的“大小”与“@”的数量不匹配,该怎么办?在输入中 - 您没有处理该错误条件。)

3)我也看到你正在为CLLocationCoordinate2D coord;分配纬度/经度,但没有对它做任何事情。这是故意的吗?