uiimage и проблема выпуска uibutton? - PullRequest
0 голосов
/ 12 января 2010

Я уже некоторое время кодирую в target-c, и мне это удобно ... но одна вещь ускользает от меня. Управление памятью. Я выпускаю, поскольку я думаю правильно, но этот фрагмент кода выдает "EXC_BAD_ACCESS" и вылетает из приложения.

Когда я комментирую и НЕ отпускаю кнопку и изображение, все работает нормально. Функция вызывается для чтения массива имен файлов изображений.

for (x=items_start;x<items_stop;x++) {

    UIButton *button;
    UIImage *buttonImage;

    buttonImage = [UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]];
    button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.tag = x;
    [button setImage:buttonImage forState:UIControlStateNormal];
    [button addTarget:self action:@selector(duplicateImage:) forControlEvents:UIControlEventTouchUpInside];

    [viewBasicItems addSubview:button];     

    [buttonImage release];
    [button release];

}

есть идеи? Как я уже сказал, когда я закомментирую последние две строки (отпуская кнопку и изображение), все работает хорошо. Это нормально или я могу их отпустить?

Примечание: я удалил немало другого кода, чтобы показать этот пример в меньшем количестве!

Ответы [ 6 ]

6 голосов
/ 12 января 2010

Экземпляр button автоматически освобожден:

button = [UIButton buttonWithType:UIButtonTypeCustom];

Вы используете удобный метод +buttonWithType: вместо пары alloc/init. Таким образом, ваше приложение будет зависать и здесь:

[button release];

Либо удалите этот оператор -release, либо используйте alloc/init для создания экземпляра представления кнопки.

Я бы порекомендовал вам использовать alloc/init, так как вы делаете все это внутри цикла for. В этом цикле вы можете создать множество объектов, которые нужно автоматически выпустить. Вероятно, лучше вручную выделить память и освободить ее.

И прочитайте руководство по управлению памятью Apple .

4 голосов
/ 12 января 2010
buttonImage = [UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]];

Ваш buttonImage объект автоматически освобожден, поэтому вы не должны отпускать его в своей функции.

С Руководство по управлению памятью :

Вы владеете только теми объектами, которые создали метод, имя которого начинается с «Alloc» или «new» или содержит «copy» (например, alloc, newObject или mutableCopy), или если вы отправите сохранить сообщение.

Редактировать: Когда Алекс указывает, ваш объект кнопки также автоматически высвобождается.

0 голосов
/ 15 мая 2014

Исправление в вашем коде следующим образом:

for (x=items_start;x<items_stop;x++) {

UIButton *button;

button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = x;
[button setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]]
               forState:UIControlStateNormal];
[button addTarget:self action:@selector(duplicateImage:) 
                   forControlEvents:UIControlEventTouchUpInside];

[viewBasicItems addSubview:button];     

[button release];

}
0 голосов
/ 07 декабря 2010

это не очень хороший метод использования [UIButton ButtonWithType:] .. потому что вы не можете ссылаться на объект .. вместо этого просто используйте

`for (x=items_start;x<items_stop;x++) {

    UIButton *button;
    UIImage *buttonImage;

    buttonImage = [UIImage alloc] initWithContentOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingString:[NSString stringWithFormat:@"/%i.png",x]]];

    button = [[UIButton alloc] init];
    button.tag = x;
    [button setImage:buttonImage forState:UIControlStateNormal];
    [button addTarget:self action:@selector(duplicateImage:) forControlEvents:UIControlEventTouchUpInside];

    [viewBasicItems addSubview:button];     

    [buttonImage release];
    [button release];

}
`
0 голосов
/ 12 января 2010

Хорошо, основы.

Большинство методов, которые создают объекты, возвращают объекты, которые были выделены, затем «автоматически выпускаются».

Вызов autorelease добавляет ваш объект в "пул autorelease", что означает, что они получат вызов release в следующий раз, когда ваше приложение посетит цикл событий.

Когда вы используете автоматически выпущенные объекты, вы можете использовать их, а затем забыть о них. Они освобождаются автоматически.

Исключением, как уже говорили другие, являются вызовы с именем "init" или "new" или вызовы методов "copy". Эти методы возвращают объекты, которые не были автоматически освобождены. Владелец этих объектов должен освободить или автоматически освободить эти объекты, чтобы их можно было освободить и не вызвать утечку памяти.

В вашем примере кода вы создаете объекты buttonImage и button с помощью вызовов + imageNamed и + buttonWithType.

Это вызовы класса, которые возвращают объект нужного типа. Поскольку они не содержат в именах слов «init» или «new», возвращаемые ими объекты уже автоматически высвобождаются, поэтому вы НЕ должны их освобождать.

Вы передаете создаваемое изображение кнопке, поэтому кнопка сохраняет изображение. Затем вы передаете объект кнопки вашему объекту viewBasicItems с помощью вызова -addSubview, поэтому представление сохраняет кнопку.

Таким образом, вы не должны больше ничего делать. Кнопка сохранит изображение, а вид сохранит кнопку.

Надеюсь, это поможет.

0 голосов
/ 12 января 2010

У вас есть три варианта:

Использовать alloc / init например;

NSString *imagePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:[NSString stringWithFormat:@"/%i.png",x]];
buttonImage = [[UIImage alloc] initWithContentsOfFile:imagePath];

и отпустите его после того, как вы закончите

[buttonImage release];

Или используйте сохранение / копирование

buttonImage = [[UIImage imageNamed:[NSString stringWithFormat:@"%i.png", x]] retain ];

и отпустите

[buttonImage release];

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

...