EXC_BAD_ACCESS на пользовательском UIView с пользовательским XIB
Я разрабатываю приложение iOS 5+ с последним SDK.
Я создал пользовательский UIView (TopMenuView
) с пользовательским XIB. В Interface Builder я изменил этот класс XIB, UIView
на TopMenuView
. Я не установил File 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];
Ответы
Ответ 1
Вот как я это сделал:
//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.
Это работает для меня.
Ответ 2
Причина, по которой он вызывает 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
}
Ответ 3
Скорее всего, вы попадаете в бесконечный цикл, потому что вы рекурсивно вызываете 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;
}
Ответ 4
Ваш - (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];
Ответ 5
Я получал ту же ошибку, пока не изменил, как я загрузил xib файл из раскадровки. В основном это связано с созданием @IBOutlet из корневого представления файла xib для кода. Также убедитесь, что вы установили File Owner 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
}
}
Мой полный ответ для настройки этого проекта здесь.