@IBDesignable崩溃代理


74

当我编写自己的UIButton-extended类并使其成为时@IBDesignable,我在Interface Builder中收到两个错误,即:

  • Main.storyboard:错误:IB Designables:无法更新自动布局状态:代理由于FD关闭而崩溃
  • Main.storyboard:错误:IB Designables:无法呈现RandjeUIButton的实例:代理崩溃

这是我的代码:

import UIKit

@IBDesignable
class RandjeUIButton: UIButton {
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        self.backgroundColor = UIColor.blackColor()
    }
}

我正在OS X 10.11 beta 2上的Xcode 7 beta 2中工作。(在VM中运行)


11
你需要重写init(frame: CGRect)以及
埃里克·钱

3
我已经做到了,关于代理的错误现在已经消除了。在身份检查器中选择标签时,现在仍然在Interface Builder中看到构建失败?
jbehrens94 2015年

1
@EricQian我还重写了重写init(frame:CGRect)和必需的init?(coder aDecoder:NSCoder)方法。仍然出现相同的错误。
Raj Aggrawal

Answers:


120

Xcode的Interface Builder要求您同时实现两个初始化器或执行两个初始化器,@IBDesignable才能在IB中正确呈现类。

如果实现,则required init(coder aDecoder: NSCoder)还需要重写init(frame: CGRect),否则“代理将崩溃”,如Xcode引发的错误所示。

为此,将以下代码添加到您的类中:

override init(frame: CGRect) {
    super.init(frame: frame)
}

12
我不认为这就是原因。我有两种方法,我是7.2。它仍然崩溃。
Alix

1
这是我的原因,我删除了init(frame: CGRect)原因,因为我只是从情节提要中对其进行了初始化。
凯尔·戈斯兰

2
@mathielo我还重写了重写init(frame:CGRect)和必需的init?(coder aDecoder:NSCoder)方法。仍然遇到相同的错误
Raj Aggrawal

1
事实证明,这对我来说是一个非常艰巨的调试挑战。我将另一个框架(Pod)中存在的类子类化。父类具有没有公共范围的init方法之一(默认为内部)。因此,init方法在我的源代码中不可见。最后,弄清楚了这一点,并在我项目的源代码中复制了父类。非常感谢!
KK

1
这两个init可能还不够。以UISegmentedControl为例,还应该实现重写init(items:[Any]?)
Bagusflyer

23

我遇到了同样的问题,并通过以下方式解决了问题:

  1. 问题:

错误:IB设计项:无法更新自动布局状态:代理崩溃

  1. 在检查文件中找到调试按钮,然后单击它。

调试

  1. 然后Xcode会告诉您问题所在。就我而言,我IBDesignable在上课之前去了。

  2. 然后我清理并重建它,错误消失了


嗨@Azure,我也正面临这个问题。Xcode(7.3)并没有使我移到代码行中,这是当我单击“调试”按钮时导致问题的原因,正如您在添加的图像上很好地显示的那样。那是Xcode的错误吗?
Sauvik Dolui '16

嗨〜您现在解决问题了吗?我也使用Xcode(7.3)。请确保选择导致崩溃的视图,然后单击调试按钮。
Azure玉

2
不要忘记在单击“调试”按钮之前创建“所有异常”断点,这样调试器将在崩溃后停止一些指令,您可以在其中单击堆栈跟踪列表中的代码,或者直接在导致崩溃的指令。
carlos_ms

11

有很多问题可以导致此。启动控制台,并查找崩溃报告IBDesignablesCocoaTouch...

我只是通过可设计的第三方解决了一个valueForKey语义上的问题。


11

在Xcode 7.3中,以上解决方案均不适用于我,但是对此问题的可接受答案是:无法呈现IB Designables实例。

  1. 清除项目的Xcode派生数据。它们在〜/ Library / Developer / Xcode / DerivedData中
  2. 按⌘⇧K清理当前版本
  3. 建立你的项目
  4. 在情节提要中,转到“编辑器”菜单,然后执行“刷新所有视图”;等待构建完成,错误应该消失

为了解决这个问题,我不需要执行第4步(并且将我的PaintCode-drawRect的UIView绘制在情节提要中),以防万一。

归功于@Mojtaba和@WeZZard


11

对我来说,没有使用#if !TARGET_INTERFACE_BUILDER它吸引了我。基本上,我有一些代码会导致访问Bundle中的路径...

Bundle.main.path(forResource: "Foo", ofType: "plist")

问题是,在IB(而不是您的应用程序)中运行时,Bundle.main不是您的应用程序...

(lldb) po Bundle.main
NSBundle </Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays> (loaded)

因此,答案只是简单地@IBDesignable UIView仔细检查代码,并在设计时运行时#if !TARGET_INTERFACE_BUILDER将其CoreLocation用于没有意义的任何事情(例如,在我的案例中为)。

我如何调试和发现这个

这是在使用故事板中Editor -> Debug Selected View选择的同时看到的内容@IBDesignable UIView

这是在情节提要板上选择<code> @IBDesignable UIView </ code>时使用<code> Editor-> Debug Selected View </ code>时看到的内容

然后,您将在正确的位置崩溃

调试导航器

就我而言,正如您所看到initXXXXassert,它在设计时崩溃了,因为它在设计时正在我的Bundle(即Xcode)中寻找文件中的值。


如果必须使用>,那么使用@IBDesignable有什么意义? #if !TARGET_INTERFACE_BUILDER
Yash Bedi

9

在任何标有@IBDesignable的类中使用UIImage时,我发现确实很重要。经典的UIImage初始化会使代理崩溃:

let myImage = UIImage(named: String) // crash the agent

解决方案是使用UIImage的以下init方法:

let myImage = UIImage(named: String, in: Bundle, compatibleWith: UITraitCollection)

工作代码示例:

let appBundle = Bundle(for: type(of: self))
let myImage = UIImage(named: "myImage", in: bundle, compatibleWith: self.traitCollection))

使用@IBDesignable关键字的self是您的类。Xcode 9.4,Swift 4.1


8

XCode 10,Swift 4.2

我在这里找到了答案

解决方案很简单-在required init?(coder aDecoder: NSCoder)我的自定义视图类的方法中更改解决捆绑的方式。

    Bundle.main.loadNibNamed(String(describing: TestView.self), owner: self, options: nil)

需要更改为

let bundle = Bundle(for: TestView.self)
bundle.loadNibNamed(String(describing: TestView.self), owner: self, options: nil)

2

这是我解决此问题的方法:

  • 确保插座正确初始化
  • @IBInspectable属性将正确初始化
  • 在xib文件中,单击“文件”的所有者占位符,转到“身份检查器”,确保它没有任何默认值

import UIKit

@IBDesignable class TestView: UIView {
    
    @IBOutlet weak var label: UILabel!
    
    
    @IBInspectable var textLabel1: String? {
        get {
            return label.text
        }
        set {
            label.text = newValue
        }
    }

    
    // MARK: Setup
    
    var view1: UIView!
    var nibName: String = "TestView"
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        xibSetup()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        xibSetup()
    }
    
    private func xibSetup() {
        view1 = loadViewFromNib()
        
        view1?.frame = self.bounds
        view1?.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
        
        if view1 != nil {
            addSubview(view1!)
            //textLabel1 = "ok"
        }
    }
    
    private func loadViewFromNib() -> UIView? {
        let bundle = NSBundle(forClass: self.dynamicType)
        let nib = UINib(nibName: nibName, bundle: bundle)
        for object in nib.instantiateWithOwner(self, options: nil) {
            if let view: UIView = object as? UIView {
                return view
            }
        }
        return nil
    }
    
    
}

用法:

在此处输入图片说明


2

只需在另一个Xcode设置系统上重新打开代码即可。就我而言,它奏效了。


这似乎在某些情况下有效。我遇到了同样的问题,尝试了所有可能无法解决的问题,最后我确实完全关闭了xcode,并打开了一个未实现任何@IBDesignable的项目,并打开了导致代理崩溃的项目,并且错误消息已消失。我没有任何有效的逻辑,但是xcode似乎有一些沼泽:(
dip

1

我在这上浪费了一整天,终于解决了我的问题 在此处输入图片说明

我选择Build for target为8.0,它为我修复了所有问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.