Использование переменных авторелиза в фоновом потоке iOS

В приложении для iOS я запускаю несколько фоновых потоков для обработки некоторого XML-кода, который возвращается из службы REST.

У меня есть несколько пользователей, которые испытывают периодические сбои в строке кода [self.names addObject: name] в PeopleParser.m. В журналах сбоев не указана причина, только строка кода, в которой произошел сбой. Я не могу воспроизвести сбой, поэтому я предполагаю, что это связано с памятью. Возможно ли, что мой объект *xml освобождается, возможно, основным пулом потоков, до того, как мой цикл for завершится с ним? Обратите внимание, что я не объявляю пул автоматического освобождения в фоновом потоке.

Фетчер.м

-(void) peopleFetchComplete:(ASIHTTPRequest *)theRequest {

    dispatch_async( backgroundQueue, ^{
       PeopleParser *xmlParse = [[PeopleParser alloc] initWithContext:[self managedObjectContext]];
       [xmlParse parseXMLData:[theRequest responseData] parseError:&parseError];
       [xmlParse release];
    });
}

PeopleParser.h

@interface PeopleParser : NSObject {
    NSMutableArray *names;
    ...
}

-(void)parseXMLData:(NSData *)data parseError:(NSError **)error;

@property (retain, nonatomic) NSMutableArray *names;

PeopleParser.m

-(id)initWithContext:(NSManagedObjectContext *)managedObjContext{
    self = [super init];
    self.managedObjectContext = managedObjContext;
    names = [[NSMutableArray alloc] init];
    return self;
}

-(void)dealloc{
    [names release];
    [managedObjectContext release];
}

@synthesize names;

-(void)parseXMLData {

    //documentWithData returns an autorelease object
    SMXMLDocument *xml = [SMXMLDocument documentWithData:someNSData error:nil];
    NSArray *people = [[document root] children];

    for (SMXMLElement *element in people) {
        NSString *name = [element attributeNamed:@"personName"];
        [self.names addObject: name];  //CRASHES HERE occasionally 
    }

    //do additional stuff with the data
    ...
}

Журнал сбоев

Тип исключения: EXC_CRASH (SIGABRT) Коды исключений: 0x00000000000000000, 0x0000000000000000 Разбитый поток: 7

След последнего исключения:

0 CoreFoundation 0x3465229e __exceptionPreprocess + 158

1 libobjc.A.dylib 0x3c37a97a objc_exception_throw + 26

2 CoreFoundation 0x3459c8d4 -[__NSArrayM insertObject:atIndex:] + 764

3 MyApp 0x000fee36 -[PeopleParser parseXMLData:parseError:] (PeopleParser.m:62)

4 MyApp 0x000e9b4c __50-[Fetcher peopleFetchComplete:]_block_invoke (Fetcher.m:818)


person iupchris10    schedule 10.09.2013    source источник
comment
Да ладно, это не настоящий код. В вызове dispatch_async нет правых скобок. Объявлено, что -initWithContext: возвращает id, но оператора возврата нет. И если у вас есть исключение, а не сбой, напечатайте, что говорит исключение.   -  person newacct    schedule 11.09.2013
comment
Извините за опечатки - я удалял вещи, которые не имели ничего общего с проблемой, на которую я пытался указать, в основном операторы NSLog и несвязанные объекты, чтобы упростить чтение кода (полагаю, никто не хочет, чтобы я публиковал 800-ю строку). сорт). Я внес изменения, чтобы исправить эти вещи. Кроме того, у меня нет исключения, потому что это ошибка, которую я не могу воспроизвести в отладчике. Журнал сбоев — это то, что есть — я бы хотел, чтобы Apple сделала его более подробным, но это не так.   -  person iupchris10    schedule 12.09.2013


Ответы (1)


Возможно, что «self.names» будет освобожден до того, как блок будет выполнен. Обязательно отмените операцию блокировки или защитите этот класс от освобождения (путем блокировки экрана с загрузочным экраном), чтобы пользователи не могли вернуться назад.

Это может произойти, например, в unloadView или в подобных местах (если вы вставите больше кода, он будет точнее).

Исходя из этого, я думаю, что исключение вызывается из метода insertObject, что означает, что вы, скорее всего, пытаетесь вставить объект «nil». Попробуйте добавить if(name) { } перед добавлением его в массив - возможно, в этом случае что-то не так с файлом XML.

person Grzegorz Krukowski    schedule 10.09.2013
comment
Нет, это не так. self захватывается блоком в точке его создания — в -(void) doFoo, вызывая на нем дополнительный retain. Однако, что, вероятно, не является потокобезопасным, так это доступ к self.names - person marko; 10.09.2013
comment
Пожалуйста, смотрите редактирование. Я добавил к вопросу значительно больше кода, а также отчет о сбое. Извините, я не добавил это раньше, я пытался ограничить область и сделать вещи простыми. - person iupchris10; 10.09.2013
comment
Хорошо, исходя из этого, я думаю, что исключение вызывается из метода insertObject, что означает, что вы, скорее всего, пытаетесь вставить нулевой объект. Попробуйте добавить if(name) { } перед добавлением его в массив - возможно, в этом случае что-то не так с файлом XML. - person Grzegorz Krukowski; 10.09.2013
comment
Я думаю, вы правы - я изменил строку кода на [self.names addObject: nil]; и получил очень похожий журнал сбоев. Должно быть, я периодически получаю неправильный XML от службы REST. Пожалуйста, отредактируйте свой ответ выше, чтобы он соответствовал вашему комментарию, и я нажму на галочку. Спасибо! - person iupchris10; 11.09.2013