EXC_BAD_ACCESS в пользовательском UIView с пользовательским XIB

Я занимаюсь разработкой приложения для iOS 5+ с последним SDK.

Я создал пользовательский UIView (TopMenuView) с пользовательским XIB. На Интерфейсном Разработчике я изменился, на этом XIB, UIView класс для TopMenuView, Я не ставил никаких File's Owner,

На TopMenuView.m Я имею:

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (self)
    {
        NSLog(@"init with coder: %d", counter);
        counter++;
        // Add custom XIB
        NSArray *topMenuView = [[NSBundle mainBundle] loadNibNamed:@"TopMenuView"
                                                             owner:nil
                                                           options:nil];
        UIView *nv = [topMenuView objectAtIndex:0];

        [self addSubview:nv];
    }

    return self;
}

Используя Interface Builder, я добавил UIView к UIViewController и изменил это UIView класс для TopMenuView,

Но когда я запускаю приложение, я получаю это сообщение журнала 4251 раз:2013-10-13 20:49:34.078 MyProject[470:c07] init with coder: 0

И тогда я получаю EXC_BAD_ACCESS Вот:

NSArray *topMenuView = [[NSBundle mainBundle] loadNibNamed:@"TopMenuView"
                                                             owner:nil
                                                           options:nil];

5 ответов

Решение

Вот как я это сделал:

//Add Custom View to my main view of viewcontroller
self.customNavView = [[CustomNavigationView alloc] init];
self.customNavView = [[[NSBundle mainBundle] loadNibNamed:@"CustomNavigationView" owner:self options:nil] objectAtIndex:0];
[self.customNavView setFrame:CGRectMake(0, 20, 320, 54)];
[self.view addSubview:self.customNavView];    

Здесь CustomNavigationView - это подкласс UIView с классом владельца файлов в качестве UIView и пользовательским классом UIView в качестве CustomNavigationView.

Это работает для меня.

Причина, по которой он так часто вызывает initWithCoder, связана с неправильной настройкой класса в вашем файле.xib.

Убедитесь, что пользовательский класс для владельца файла является вашим пользовательским классом UIView:

введите описание изображения здесь

И убедитесь, что класс в корневом представлении является UIView по умолчанию:

введите описание изображения здесь

И теперь это все, что вам нужно в вашем пользовательском классе (в Swift):

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    let view = NSBundle.mainBundle().loadNibNamed("TopMenuView", owner: self, options: nil)[0] as! UIView
    self.addSubview(view)
    view.frame = self.bounds
}

Скорее всего, вы попали в бесконечный цикл, потому что вы вызываете рекурсивно initWithCoder, Один из обходных путей - сначала проверить, есть ли у вашего подкласса какие-либо подпредставления.

-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        if (self.subviews.count == 0) {
            NSArray *topMenuView = [[NSBundle mainBundle] loadNibNamed:@"TopMenuView" owner:nil options:nil];
            UIView *nv = [topMenuView objectAtIndex:0];
            [self addSubview:self.view];
        }
    }
    return self;
}

Ваш - (id)initWithCoder:(NSCoder *)aDecoder называется всякий раз, когда TopMenuView создается путем загрузки вашего XIB.

Таким образом, вы рекурсивно называете initWithCoder:


Прокомментируйте весь ваш метод - (id)initWithCoder:(NSCoder *)aDecoder

и где вы хотите использовать TopMenuView вероятно, в каком-то контроллере используйте код ниже

NSArray *topMenuView = [[NSBundle mainBundle] loadNibNamed:@"TopMenuView" owner:nil options:nil];
UIView *nv = [topMenuView objectAtIndex:0];

Я получал ту же ошибку, пока не переделал, как я загружал файл XIB из раскадровки. По сути, это включало создание @IBOutlet из корневого представления файла xib в коде. Также убедитесь, что вы установили для владельца файла xib свой собственный класс.

import UIKit
class ResuableCustomView: UIView {

    @IBOutlet var view: UIView!
    @IBOutlet weak var label: UILabel!

    @IBAction func buttonTap(sender: UIButton) {
        label.text = "Hi"
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        NSBundle.mainBundle().loadNibNamed("ReusableCustomView", owner: self, options: nil)[0] as! UIView
        self.addSubview(view)
        view.frame = self.bounds
    }
}

Мой полный ответ по настройке этого проекта здесь.

Другие вопросы по тегам