Проблема с удалением подпредставления и последующим добавлением его - PullRequest
0 голосов
/ 02 мая 2011

У меня проблема с удалением подпредставления, или, точнее, с проверкой, осталось ли оно после удаления.

Мое приложение сначала добавляет подпредставление к self.view.

[self.view addSubview:tabsClippedView];

Затем он добавляет другое подпредставление к этому подпредставлению (к которому он добавляет несколько кнопок в качестве подпредставлений, но я думаю, что это неважно в этом контексте):

[tabsClippedView addSubview:tabsView];

Наконец, у меня есть метод, который позволяет удалить tabsView, а затем создать его снова. Мне нужно сделать это, чтобы обновить количество кнопок в этом tabsView (так как пользователь может удалять кнопки). Метод выглядит в основном так:

[self.tabsView removeFromSuperview];

После этого я вызываю метод showTabs (который я уже вызывал в самом начале приложения для добавления подпунктов). Вот где все это становится проблематичным, и где мое приложение вылетает (я не получаю ошибки в консоли отладки, поэтому я не знаю, в чем проблема ...):

    if ([tabsClippedView isDescendantOfView:self.view]) {
    NSLog(@"There is already a tabsClippedView.");
} else {
    NSLog(@"There is no tabsClippedView. I'll add one...");
    [self initTabsClippedView];
}

Здесь происходит сбой приложения: при попытке оценить, является ли tabsView isDescendantOfView (я не получаю ни одного из следующих журналов):

if ([tabsView isDescendantOfView:tabsClippedView]) {
    NSLog(@"There is already a tabsView");
} else {
    NSLog(@"There is no tabsView for the buttons. I'll add one including buttons.");
    [self initTabs];
}

Буду признателен за любые предложения, где может быть проблема.


EDIT:

Вот способы настройки моих представлений:

-(void) initTabsClippedView { // sets up tabsClippedView

NSLog(@"initTabsClippedView method started...");

CGRect tabsClippedFrame = CGRectMake(258,30,70,81*6);
tabsClippedView = [[[UIView alloc] initWithFrame:tabsClippedFrame] autorelease];
tabsClippedView.clipsToBounds = true;

[self.view addSubview:tabsClippedView];

NSLog(@"initTabsClippedView method ended.");

}

    -(void) initTabs {          

    NSLog(@"initTabs started. Adding buttons to tabsClippedView...");

    CGRect tabsFrame = CGRectMake(-30,0,50,480);
    tabsView = [[[UIView alloc] initWithFrame:tabsFrame] autorelease];
    [tabsClippedView addSubview:tabsView];  
// sets up buttons in tabsClippedView

И вот где я удаляю tabsClippedView (запускается кнопкой, найденной в tabsClippedView):

 -(void)tabDelete:(id)sender
{
    UIButton *button = (UIButton *)sender;

    [UIView animateWithDuration:0.75
                          delay:0
                        options:UIViewAnimationOptionCurveEaseIn
                     animations:^{

                                    button.transform = CGAffineTransformMakeTranslation(-30, 0);                 

                     }
                     completion:^(BOOL finished){


                         [UIView animateWithDuration:0
                                               delay:0
                                             options:UIViewAnimationOptionCurveEaseIn
                                          animations:^{

                                              [self.tabsView removeFromSuperview];

                                              //...                                           
                                          }
                                          completion:^(BOOL finished){

                                              NSLog(@"tabsView removed from Superview. Objects Deleted.");
                                              [self showTabs]; 
                                              NSLog(@"TabDelete finished. Button removed and tabsView updated accordingly.");

                                          }
                          ];    
                     }];

И это метод showTabs, который уже вызывался при запуске приложения:

- (void) showTabs {

NSLog(@"showTabs started...");

currentView = @"Tabs";

if ([tabsClippedView isDescendantOfView:self.view]) {
    NSLog(@"There is already a tabsClippedView.");
} else {
    NSLog(@"There is no tabsClippedView. I'll add one...");
    [self initTabsClippedView];
}

if ([tabsView isDescendantOfView:tabsClippedView]) {
    NSLog(@"There is already a tabsView");
} else {
    NSLog(@"There is no tabsView for the buttons. I'll add one including buttons.");
    [self initTabs];
}

Ответы [ 2 ]

1 голос
/ 02 мая 2011

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

self.tabsClippedView = [[[UIView alloc] initWithFrame:tabsClippedFrame] autorelease];

и

self.tabsView = [[[UIView alloc] initWithFrame:tabsFrame] autorelease];
1 голос
/ 02 мая 2011

Возможно ли, что вы получаете EXC_BAD_ACCESS?Возможно ли, что приложение аварийно завершает работу, потому что tabsView освобождается при отправке на него isDescendantOfView:.Если вы запускаете с включенными точками останова, он должен сообщить вам причину сбоя.Если это проблема EXC_BAD_ACCESS, попробуйте NSZombie.

. Чтобы активировать NSZombie, сделайте следующее:

  1. Получите информацию об исполняемом файле.
  2. Goк вкладке аргументов.
  3. В разделе «Переменные для установки в среде:» добавьте:

Имя: NSZombieEnabled Значение: ДА

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

РЕДАКТИРОВАТЬ: Только что увидел ваше редактирование.Я думаю, что прибил это.Вы автоматически высвобождаете представления при их создании, поэтому, когда они удаляются из своих суперпредставлений, они больше не сохраняются и, таким образом, освобождаются.В вашем приложении происходит сбой, потому что вы пытаетесь запустить методы для освобожденных представлений.

РЕДАКТИРОВАТЬ 2: Думаю, я должен сказать вам, что есть лучшее решение, чем опубликованное Praveen S.

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

[tabsClippedView release];
tabsClippedView = [[UIView alloc] initWithFrame:tabsClippedFrame];

и

[tabsView release];
tabsView = [[UIView alloc] initWithFrame:tabsFrame];

Приведенный выше код действует так же, как код, опубликованный Praveen S, но безautorelease.Авто-релиз дороже, чем обычный выпуск, и его следует использовать только при необходимости, и в этом случае это не так.

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

[tabsView removeFromSuperview];
[tabsView release];
tabsView = nil;

или просто

[tabsView removeFromSuperview];
self.tabsView = nil;

, а затем вместо:

if ([tabsView isDescendantOfView:tabsClippedView]) ...

вы можете использовать:

if (tabsView) ...

Как вы могли заметить, вам действительно не нужно сохранять вид.Вы также можете сделать следующее:

tabsView = [[UIView alloc] initWithFrame:tabsFrame];
[tabsClippedView addSubview:tabsView]; // This retains tabsView
[tabsView release];

, а затем удалить вид, который будете использовать:

[tabsView removeFromSuperview]; // This will release the tabsView
tabsView = nil;

Также не забудьте установить nil в viewDidUnload.

РЕДАКТИРОВАТЬ 3: Почему self сделал такую ​​разницу:

Вам нужно понять, как работают свойства и счетчик ссылок.Есть книги и такие, о которых вы могли бы прочитать.Я уверен, что Google также может предоставить вам несколько хороших ссылок.

Разница между

self.tabsView = [[UIView alloc] initWithFrame:frame];

и

tabsView = [[UIView alloc] initWithFrame:frame];

в том, что self.tabsView осуществляет доступустановщик свойств, в то время как tabsView непосредственно обращается к переменной экземпляра.

Реализация неатомического свойства сохранения выглядит примерно так:

- (void)setTabsView:(UIView *)view
{
    if (view != tabsView) {
        [tabsView release];
        tabsView = [view retain];
    }
}

Таким образом, свойство заботится оуправление памятью для вас.В моем решении я сам позабочусь об управлении памятью, и поэтому мне не нужно это свойство для меня, поэтому я им не пользуюсь.

Надеюсь, это объясняет, почему self сделал такую ​​разницу.

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