iphone: утечка памяти с использованием NSString - PullRequest
0 голосов
/ 17 февраля 2012

У меня есть небольшой фрагмент кода, который обновляет ALAssetGroup (фотоальбом), если пользователь вносит изменения в свою библиотеку фотографий:

- (void) ALAssetsLibraryChangedNotification
{
    [[self activityIndicator] startAnimating]; 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [[self library] enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop)
    {
        if (group != nil)
        {
            NSString *newAlbumID = [[NSString alloc] initWithString: [group valueForProperty: ALAssetsGroupPropertyPersistentID]]; 

            if ([newAlbumID isEqualToString: self.albumID])
            {
                self.album = group;
                [self loadPhotos];
                [newAlbumID release];
                return;
            }

            [newAlbumID release];
        }

    }
    failureBlock:^(NSError *error) 
    {
    }];

    [pool release];

}

Это работает, но только так долгоЯ получаю "signalbrt" и соответствующий "-[UIButtonContent isEqualToString:]: unrecognized selector sent to instance", чтобы согласиться с ним (иногда вместо UIButtonContent будет NSArray).Я также включил зомби и получил сообщения типа "*** -[CFString release]: message sent to deallocated instance" and "*** -[CFString class]: message sent to deallocated instance".Я попытался распределить строку разными способами, ни один из которых не работал правильно.Кто-нибудь знает, что здесь происходит?

Ответы [ 3 ]

0 голосов
/ 17 февраля 2012

Моим первым предположением будет подозрение, что self.albumID или self.album объявлены как assign, а не retain или copy, или что-то не так в loadPhotos. Проверьте объявления для этих свойств и временно удалите вызов loadPhotos. Это все еще терпит крах?

Два выпуска для строки, которую вы размещаете, кошерны, но способ организации кода затрудняет рассуждение. Вы должны выполнить рефакторинг, чтобы строка была либо автоматически освобождена, либо выпущена один раз.

0 голосов
/ 18 февраля 2012

Я думаю, что проблема, скорее всего, связана с переменной 'group' и / или с вызовом 'valueForProperty' для этой групповой переменной. Это может быть выпущено под вами где-то. Таким образом, когда вы инициализируете свой 'newAlbumId' из свойства переменной 'group', вам присваивается указатель на случайную память (так как объект группы или был освобожден), который в конечном итоге становится указателем на UIButtonContent. или иногда и «NSArray». Выполнение isEqualToString, таким образом, возвращает ошибку, которая выдается. Именно поэтому вы получаете предупреждения с включенными зомби.

Когда у вас включена функция NSZombies, вы получаете какие-либо предупреждения относительно доступа к групповой переменной?

Кроме того, как управляется объект, на который ссылается память групповой переменной - вы выделяете / инициализируете и назначаете его непосредственно iVar в содержащем объекте (а не как свойство через средство доступа к свойству)? Если это так, убедитесь, что вы не «освобождаете» его после этого alloc, поскольку, поскольку оно не является свойством, оно не сохраняется в назначении iVar - вам нужно всего лишь освободить его в своем методе dealloc (или настроить его как свойство вместо).

Просто взглянув на класс ALAssetsGroup, вы, скорее всего, инициализируете группу iVar, присваивая результат вызова вспомогательного метода - если это так, этот вспомогательный метод автоматически высвобождает возвращаемый им объект группы, поэтому вам нужно убедиться, что вы «сохранили» значение, когда вы присваиваете его переменной вашей группы в содержащем объекте. (или, возможно, проще, сделайте group сохраняющим свойством содержащегося в нем объекта и назначьте его с помощью метода доступа к свойству).

0 голосов
/ 17 февраля 2012

попробуй

        NSString *newAlbumID = [[NSString alloc] initWithString: [group valueForProperty: ALAssetsGroupPropertyPersistentID] autorelease]; 

и удалите другие выпуски для этого объекта.

...