Память после воссоздания NSMutableArray переинициализирована - PullRequest
0 голосов
/ 19 октября 2011

У меня есть класс, который имитирует поведение UIImagePickerController, за исключением некоторых тонких различий.В моем классе я использую только один контроллер представления и использую его, чтобы поменять местами просмотр таблиц альбомов и фотографий, когда пользователь делает выбор строки / эскиза.Таким образом, последовательность событий, которая вызывает у меня проблемы, выглядит следующим образом:

  1. Я выбираю альбом
  2. Загружается просмотр таблицы фотографий, и я нажимаю кнопку "Назад", чтобы вернуться к альбомам.tableview
  3. Альбомы загружаются при просмотре таблицы
  4. Я выбираю альбом, и теперь возникает ошибка доступа к памяти

Я реализовал оба представления таблицы и массив в ivarsследующим образом:

@property (nonatomic, retain) UITableView *selectAnAlbumTableView, *selectAPhotoTableView;
@property (nonatomic, retain) NSMutableArray *albums, *photos;
@property (nonatomic, retain) ALAssetsGroup *album;
@property (nonatomic, retain) UIActivityIndicatorView *spinner;

Одно из различий между представлением таблицы альбомов и представлением таблицы фотографий состоит в том, что просмотр таблицы фотографий воссоздается каждый раз, когда пользователь выбирает альбом, и именно здесь возникает ошибка.Первоначально "EXC_BAD_ACCESS" происходило, когда я удалял представление таблицы, как я делаю здесь:

        [[self selectAPhotoTableView] removeFromSuperview];
        [selectAPhotoTableView release];
        selectAPhotoTableView = nil;
        [photos release];
         photos = nil;

Я заметил, что ошибка происходит в [photos release].Фотографии - это массив, в котором я храню все кнопки миниатюр, которые помещаются в ячейки на табличном представлении фотографий.Если я удаляю [photos release] и photos = nil, тогда проблема возникает при фактическом создании табличного представления (как я уже упоминал вначале):

NSMutableArray *photosTemp = [[NSMutableArray alloc] init];
[self setPhotos: photosTemp];
[photosTemp release];

Теперь после EXC_BAD_ACCESS выдается «EXC_BAD_ACCESS»линия.Кто-нибудь знает, что я здесь не так делаю?

ОБНОВЛЕНИЕ: Я поставил неправильный код, где ошибка возникает во второй раз, теперь она исправлена.

Ответы [ 2 ]

1 голос
/ 20 октября 2011

Я помещу это в ответ, а не в массивный комментарий.

Эта строка (см. Комментарии) вызовет проблему:

thumbnailImage = [UIImage imageWithCGImage:[theALAsset thumbnail]]; 

Этопотому что thumbnailImage является иваром. UIImage imageWithCGImage возвращает вам автоматически выпущенный объект.Поэтому вы должны сохранить его либо явно, как указано ниже:

thumbnailImage = [[UIImage imageWithCGImage:[theALAsset thumbnail]] retain]; 

Или вы можете позволить своему свойству сделать это за вас с помощью сгенерированных сеттеров.Установка свойства следующим образом ничего не изменит, потому что в приведенной выше строке вы ссылаетесь на thumbnailImage напрямую, а не через установщики.

@property (nonatomic, retain) UIImage *thumbnailImage;

Вам нужно использовать self,таким образом, у вас есть:

self.thumbnailImage = [UIImage imageWithCGImage:[theALAsset thumbnail]]; 

. Он будет проходить через сгенерированные сеттеры, которые сначала проверяют любой существующий объект, release, если он есть, а затем retain для вашего вновь назначенного объекта.Все это происходит автоматически.Другими словами, это избавляет вас от необходимости делать:

-(void)setThumbnailImage:(UIImage *)aThumbnailImage
{
    [aThumbnailImage retain];
    if (thumbnailImage)
    {
        [thumbnailImage release];
    }
    thumbnailImage = aThumbnailImage;
}

Книга Аарона Хиллегаса содержит отличное объяснение этого материала в "Программирование какао для Mac OS X".

Ключевым моментом является запуск сборок с помощью Analyzer или просто время от времени запускать Analyzer.Он обнаружит многие из этих проблем, прежде чем вы перейдете к длительному процессу отслеживания ошибок EXC_BAD_ACCESS.

0 голосов
/ 20 октября 2011

EXC_BAD_ACCESS означает, что вы указали недопустимый указатель (и в этом контексте nil можно считать «действительным»). В вашем первом случае этот плохой указатель будет выглядеть как photos.

Если бы это была автоматическая переменная, это могло бы быть плохо, потому что вы не смогли инициализировать ее, но система всегда обнуляет переменные экземпляра.

Таким образом, либо вы присвоили ему что-то недопустимое, либо значение, которое было в нем, все еще там, но объект, к которому он адресован, был освобожден.

Ошибка во втором случае странным образом говорит о том, что «я» было выпущено. Это может быть вашей корневой проблемой, и ваш dealloc метод выпускает photos, так что сначала выдается ошибка. Я бы посоветовал вам поместить NSLog в вашу подпрограмму dealloc, чтобы посмотреть, будет ли он вызываться слишком рано, и, если это так, то, очевидно, выяснить, как вам не удалось должным образом сохранить объект контроллера.

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