2013-08-18 1 views
4

У меня есть подкласс NSManagedObject с несколькими атрибутами «целое число 32», которые действительно перечислены. Эти перечисления определены в файле .h моей модели, как это:Нашел NSZombie в моем приложении ... теперь что?

typedef enum { 
    AMOwningCompanyACME, 
    AMOwningCompanyABC, 
    AMOwningCompanyOther 
} AMOwningCompany; 

Мне нужно, чтобы показать вид таблицы, которая отображает значение каждого атрибут этого пользовательского объекта, поэтому для каждого перечисления У меня есть метод, который выглядит как это возвращать строковые значения:

-(NSArray*)stringsForAMOwningCompany 
{ 
    return [NSArray arrayWithObjects:@"ACME Co.", @"ABC Co.", @"Other", nil]; 
} 

на моем взгляде таблицы, я перебираю атрибуты моей NSManagedObject (с использованием NSEntityDescription «s attributesByName и для каждого атрибута я называю вспомогательный метод, который вызывает соответствующий метод„stringsFor“в верните строки для этого конкретного атрибута:

-(NSArray*)getStringsArrayForAttribute:(NSString*)attributeName 
{ 
    SEL methodSelector = NSSelectorFromString([self methodNameForAttributeNamed:attributeName]); 
    NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:[[AMProperty class] instanceMethodSignatureForSelector:methodSelector]]; 
    [invocation setSelector:methodSelector]; 
    [invocation setTarget:self.editingPole]; 
    [invocation invoke]; 

    NSArray* returnValue = nil; 
    [invocation getReturnValue:&returnValue]; 

    return returnValue; 
} 

Мой вид таблицы cellForRowAtIndexPath выглядит следующим образом:

... 
NSString* itemName = self.tableData[indexPath.row]; 
NSAttributeDescription* desc = itemAttributes[itemName]; 

NSString* cellIdentifier = [self cellIdentifierForAttribute:desc]; // checks the attribute type and returns a different custom cell identifier accordingly 
if ([cellIdentifier isEqualToString:@"enumCell"]) 
{ 
    // dequeue cell, customize it 
    UITableViewCell* enumCell = ... 
    ... 
    NSArray* stringValues = [[NSArray alloc] initWithArray:[self getStringArrayForAttribute:itemName]]; 
    int currentValue = [(NSNumber*)[self.editingPole valueForKey:itemName] intValue]; 
    enumCell.detailTextLabel.text = (NSString*)stringValues[currentValue]; 
    return enumCell; 
} 
... 

Для только один из атрибутов, я получаю аварии на обратном массиве NSInvocation «s:

-[__NSArrayI release]: message sent to deallocated instance 0x856a4b0 

Используя Зомби Профилировщик, я вижу:

Instruments Screenshot

Я использую ARC. Как я могу отладить это дальше?

ответ

8

Недавно я столкнулся с очень похожими проблемами, и мне потребовалось некоторое время, чтобы понять, что я делаю неправильно. Здесь выдается дополнительный выпуск, потому что ваш указатель returnValue равен __strong (по умолчанию), ARC считает, что объект принадлежит этому указателю, но это не тот случай.

-[NSInvocation getReturnValue:] не принимает на себя ответственность, а «назначение» через адрес указателя обходит objc_storeStrong(), который обычно использует ARC.

Решение прост: отметьте указатель как __unsafe_unretained. Это правда; объект не сохраняется через этот указатель (как если бы он был __strong), и ARC не должен его выпускать здесь.

+0

Amazing. Спасибо. Я никогда полностью не понимал управление памятью в Objective-C, и с ARC я думал, что мне тоже не нужно беспокоиться. Ясно, что не верно;) – Shinigami

+0

Обычно вы этого не делаете, но передача объектов через 'void *' - это своего рода лунная бахрома. –

 Смежные вопросы

  • Нет связанных вопросов^_^