【问题标题】:EXC_BAD_ACCESS on custom UIView with custom XIB带有自定义 XIB 的自定义 UIView 上的 EXC_BAD_ACCESS
【发布时间】:2013-10-21 17:10:38
【问题描述】:

我正在使用最新的 SDK 开发 iOS 5+ 应用程序。

我创建了一个带有自定义 XIB 的自定义 UIView (TopMenuView)。在 Interface Builder 上,我已在此 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];

【问题讨论】:

  • 您将 nv 添加为子视图,但您的主视图在哪里?您没有向文件所有者声明任何视图。您必须将一个视图附加到文件的所有者。

标签: ios objective-c uiview


【解决方案1】:

它多次调用 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
}

【讨论】:

  • 这确实解决了问题。只是觉得 Xcode 应该对这些 custom class 配置提供更好的警告。
  • @JYeh 这是一个详细而准确的答案。
  • 另外请注意,如果您的自定义类来自另一个项目,例如 Cocoapods 依赖项,那么您也需要填写 Module 字段(就在自定义类下方)。
  • 我花了好几天才弄明白。为什么苹果不能给出一些更有意义的错误信息?
  • 你是这个英雄的英雄。
【解决方案2】:

您很可能会陷入无限循环,因为您正在递归调用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;
}

【讨论】:

    【解决方案3】:

    我就是这样做的:

    //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 覆盖
    【解决方案4】:

    只要通过加载您的 xib 创建 TopMenuView,就会调用您的 - (id)initWithCoder:(NSCoder *)aDecoder。

    因此你递归地调用你的initWithCoder:


    评论你所有的方法- (id)initWithCoder:(NSCoder *)aDecoder

    你想在哪里使用TopMenuView 可能在某些控制器中使用下面的代码

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

    【讨论】:

    • 是的,我知道。我该如何解决?
    【解决方案5】:

    在我重新修改从情节提要加载 xib 文件的方式之前,我遇到了同样的错误。基本上它涉及从 xib 文件的根视图到代码创建一个@IBOutlet。还要确保将 xib 的 File's Owner 设置为自定义类。

    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
        }
    }
    

    我设置这个项目的完整答案是here。

    【讨论】:

      猜你喜欢
      • 2015-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      • 2018-06-15
      • 2015-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多