Может ли быть проблема с макс.емкость памяти?Или почему эта переменная частично освобождена? - PullRequest
0 голосов
/ 22 июля 2011

Я занимаюсь разработкой приложения для iPad и столкнулся с действительно странной проблемой. Я постараюсь объяснить это как можно лучше.

У меня есть класс с именем TranslationObject, который содержит ключ и текстовое значение. Я создал этот класс следующим образом:

@interface TranslationObject : NSObject {
    NSNumber *_key;
    NSString *_value;
}

@property (nonatomic, retain) NSNumber *key;
@property (nonatomic, retain) NSString *value;

- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value;

@end

Переводы будут извлечены из XML или БД в будущем, но сейчас я делаю следующее:

@interface Translation : NSObject {
    NSMutableArray *m_extfeat;
}

@property (nonatomic, retain) NSMutableArray *extfeat;

+ (Translation *) getInstance;
- (id) init;
- (NSMutableArray *) getExtFeat;

@end

Реализация:

@implementation Translation

@synthesize extfeat = m_extfeat;

- (id) init {
    self = [super init];

    if (self) {
        m_extfeat = [[self getExtFeat] retain];
    }
    return self;
}

- (NSMutableArray *) getExtFeat {
    TranslationObject *obj1 = [[[TranslationObject alloc] initWithKey:[NSNumber numberWithInt: 0] andValue:@"Animal house"] autorelease];

    .... more items declared ....

    NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14, obj15, obj16, obj17, nil];

    return [array autorelease];
}
@end

Эти переводы используются в UITableViewController и извлекаются в методе viewDidLoad как:

- (void)viewDidLoad
{
     _data = [[Translation getInstance].extfeat retain];
}

Я использую эти значения в cellForRowAtIndexPath, где я вызываю метод для настройки ячейки:

- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *) indexPath {
    TranslationObject *object = (TranslationObject *) [_data objectAtIndex:indexPath.row];

    //Crashes here at 13th item:
    NSLog("Object key: %@", [object.key stringValue]);
}

Как показывает приведенный выше фрагмент, странно, что приложение вылетает при получении значения ключа , только если массив _data содержит более 12 элементов . Так что, если я заполню переменную _data только 12 элементами или меньше, мой код будет работать нормально. Если я добавлю более 12, приложение вылетает, как только получает 13-й объект.

Итак, я включил NSZombies, и поэтому, когда я проверяю 13-й элемент в этом методе, значение все еще в порядке, но только ключ превратился в зомби. И снова .. Только с 13-го пункта!

Кто-нибудь знает, как это возможно? Может быть так, что в памяти есть максимальное количество элементов? Память заполнена на 12 элемент? Но если бы это было так, то почему значение все еще там? Как могло случиться, что это просто key , который выпускается раньше ?! И как?!

Надеюсь, это объяснение имеет смысл, и кто-то может пролить свет на этот случай .. = /

Спасибо!

РЕДАКТИРОВАТЬ: Вот реализация метода initWithKey объекта TranslationObject:

- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value {

    self = [super init];

    if (self) {
        _key = key;
        _value = value;
    }

вернуть себя; }

1 Ответ

1 голос
/ 23 июля 2011

Убедитесь, что вы используете методы доступа к свойству в TranslationObject или сохраняете номер:

@implementation TranslationObject

@synthesize key=_key, value=_value;

- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value {
    self = [super init];
    if (!self) return nil;

    self.key = key;  // ensures key is retained
    self.value = value;

    return self;
}

…

@end

Особенности:

self.key = key;

- это синтаксис для вызова методов доступа дляимущество;в этом случае устанавливается аксессор.Учитывая, что вы объявили свое свойство с атрибутами nonatomic и retain следующим образом:

@property (nonatomic, retain) NSNumber *key;

набор доступа будет выглядеть примерно так:

- (void)setKey:(NSNumber *)value {
    if (value != _key) {
        id old = _key;
        [value retain];
        _key = value
        [old release];
    }
}

Набор доступа автоматически генерируетсякомпилятор при добавлении:

@synthesize key=_key;

И наоборот, вызов

_key = key;

просто копирует значение указателя в key в _key, но не retainобъект, на который ссылается key.TranslationObject не предполагает владения ключом .Если вы не хотите использовать метод доступа, правильная реализация будет

_key = [key retain];
...