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
}
}
Мой полный ответ по настройке этого проекта здесь.