类初始化破坏应用程序

BOM*_*MEz 0 iphone xcode cocoa-touch objective-c

我最近为我的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
Run Code Online (Sandbox Code Playgroud)

这是我在另一个类中对它进行的调用:

self.gps = [[GPSCoordinate alloc] initWithData:gpsRawData size:[[gpsRawData componentsSeparatedByString:@"@"] count]];
Run Code Online (Sandbox Code Playgroud)

我哪里错了?

Lil*_*ard 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
    }];
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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