Приложение, нарушающее инициализацию класса - PullRequest
0 голосов
/ 29 октября 2010

Недавно я создал новый класс для своего приложения для 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 ]

6 голосов
/ 29 октября 2010

Я вижу ряд проблем.

  • Вы не проверяете возвращаемое значение [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(это будет работать на устройствах с iOS до версии 4.0):

    for (NSString *line in tokens) {
        // body of loop
    }
    
  • Вы не проверяете правильность своих данных.Если строка содержит «foo», ваша программа вылетит при попытке доступа к [lineTokens objectAtIndex:1].Аналогичным образом произойдет сбой, если у вас будет строка «foo:», когда он попытается удалить первый символ переменной coordinates.На самом деле все, что меньше 2 символов после двоеточия, потерпит крах.Он также будет аварийно завершен, если после двоеточия не будет пробелов.

  • И, наконец, все эти вызовы -release в конце завершатся аварийно.Все 4 из этих объектов являются автоматически выпущенными объектами, поэтому, вызывая для них -release, вы просто гарантируете, что приложение будет аварийно завершать работу при истечении пула автоматического выпуска.
  • Вы также сохраняете coords (например, строка) в вашем массиве coordinates.Предположительно, вы хотели сохранить coord, хотя вам нужно будет обернуть его в NSValue, чтобы сохранить в NSArray.
2 голосов
/ 29 октября 2010

Я вижу несколько проблем.

1) Самое главное, вы выпускаете много объектов, которые вы не выделяли.Например:

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

неверно.Просмотрите Правила управления памятью какао .

2) Почему вы делаете [[gpsRawData componentsSeparatedByString:@"@"] count, чтобы передать размер методу initWithData:size:, когда вам просто нужно будет повторить-componentsSeparatedByString: вызов внутри вашего метода.Передача отдельного «размера» ничего не дает, включает в себя избыточный анализ ввода и открывает больше возможных ошибок (что, если вызывающая сторона передает «размер», который не соответствует числу «@»)на входе - вы не обрабатываете это условие ошибки).

3) Я также вижу, что вы назначаете широту / долготу для CLLocationCoordinate2D coord;, но ничего с этим не делаете.Это умышленно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...