#iphone #objective-c #memory-management
#iPhone #objective-c #управление памятью
Вопрос:
Я пытаюсь лучше понять управление памятью. Если у меня есть функция, которая возвращает автоматически освобождаемый NSArray, подобный этому
// DataClass
- (NSArray *)getData {
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
// do some stuff to get data from sqlite
return array;
}
затем в другом файле класса я хочу использовать этот getData . У меня есть свойство
@property (nonatomic, retain) NSArray *myData;
- viewDidLoad {
NSMutableArray *data = [[NSMutableArray alloc] init];
data = [DataClass getData];
self.myData = data;
[data release];
}
Почему в этом случае я получаю ошибку bad access? Я знаю, что это из-за [освобождения данных], но я подумал, что, поскольку метод getData возвращает автоматически освобождаемый NSArray, и поскольку я инициализирую новый NSMutableArray с помощью alloc / init, тогда мне нужно будет его освободить? Или происходит то, что, хотя я инициализирую данные с помощью alloc / init, я даже не использую его, потому что с помощью инструкции data=[DataClass getData] я указываю на другой NSArray, а затем пытаюсь освободить этот уже автоматически освобожденный NSArray из getData, а затем данные NSMutableArray все еще плаваютгде-то в памяти? Заранее спасибо.
Комментарии:
1. Этот код может быть записан как
self.myData = [DataClass getData];
.
Ответ №1:
Ваше предположение верно. 🙂
Прежде всего, как написано, в viewDidLoad
вас утечка data
вы выделяете / инициализируете в строке 1, когда вы присваиваете data
результат вызова getData
в строке 2.
И тогда, вы правы, то, что data
в данный момент указывает на автоматически выпущенный объект. Так что обращение release
к нему — это плохо.
Честно говоря, в вашем viewDidLoad
методе вам вообще не нужен вызов to getData
. Полная и подходящая последовательность для такого рода операций:
NSMutableArray *array = [[NSMutableArray alloc] init];
// here is where you could fill array with your data, or call a method to
// which you pass array to be filled.
self.data = array;
[array release];
предполагая, что свойство data определено с retain
помощью . Используя self.
префикс, вы получаете retain
результат за себя.
Помогает ли это?
Ответ №2:
С вашим кодом возможны две проблемы. Первое несомненно:
NSMutableArray *data = [[NSMutableArray alloc] init];
data = [DataClass getData];
Это неправильный шаблон для инициализации объектов. Давайте предположим, что вызываемый метод класса getData
существует и делает то, что вы хотите (что может быть не так, подробнее об этом позже). Первая строка выделит память для нового массива и вернет указатель на него. Затем вторая строка немедленно переназначит этот указатель, чтобы указать на другой (автоматически освобожденный) массив, пропуская первый массив в процессе.
Во-вторых, ваш getData
метод имеет следующую подпись:
- (NSArray *)getData;
Подразумевается, что это метод экземпляра, то есть вы отправляете его экземпляру DataClass
. Однако ваш код, вызывающий метод, делает это, отправляя сообщение самому классу, а не его экземпляру. Возможно, это просто опечатка в вашей публикации, но лучше перестраховаться, чем потом сожалеть.