2010-01-12 2 views
0

Я уже некоторое время программировал в объективе-с, и мне это удобно ... но одна вещь ускользает от меня. Управление памятью. Я выпускаю как я думаю, что верен, но этот бит кода бросает «EXC_BAD_ACCESS» и сбой приложения.проблема с выпуском uiimage и uibutton?

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

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

Экземпляр button является autoreleased:

button = [UIButton buttonWithType:UIButtonTypeCustom]; 

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

[button release]; 

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

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

И действительно читайте memory management guide от Apple.

+0

Я вижу! Это объясняет. Спасибо за помощь. –

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

Ваш buttonImage объект autoreleased так что вы не должны освободить его в функцию.

От Memory management guide:

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

Edit: Как Алекс указывает ваш объект кнопки будет autoreleased также.

+0

спасибо за помощь и отличную цитату! –

0

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

Используйте Alloc/инициализации , например;

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 релиз];

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

0

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

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

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

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

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

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

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

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

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

Я надеюсь, что это поможет.

0

это не хороший метод использования [UIButton ButtonWithType:] .. сог вы не можете в object..instead разблокировки, этого ЮС использования

`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

Fixing в коде следующим образом:

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]; 

} 
Смежные вопросы