@IBDesignable 崩溃剂

@IBDesignable crashing agent

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

这是我的代码:

import UIKit

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

        self.backgroundColor = UIColor.blackColor()
    }
}

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

Xcode 的 Interface Builder 要求您实现 both or nether initializer for @IBDesignable classes 在 IB 中正确呈现。

如果您实施 required init(coder aDecoder: NSCoder),您还需要重写 init(frame: CGRect),否则 "the agent will crash",如 Xcode.[=14= 抛出的错误所示]

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

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

有无数的问题会导致这种情况。启动控制台,并查找崩溃报告 IBDesignablesCocoaTouch...

我刚刚解决了第 3 方可设计的问题,该问题与 valueForKey 语义有关。

我遇到了同样的问题,并且是这样解决的:

  1. 问题:

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

  1. 在检查文件中找到调试按钮并点击它。

  1. 然后Xcode会告诉你问题出在哪里。 在我的例子中,我在 class.

  2. 之前删除了 IBDesignable
  3. 然后我清理并重建它,错误消失了

我是这样解决这个问题的:

  • 确保插座已正确初始化
  • @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
    }
    
    
}

用法:

在 Xcode 7.3 中,上述解决方案中的 none 对我有用,但对这个问题的接受答案确实如此:Failed to render instance of IB Designables

  1. Clear Xcode derived data for the project. They are in ~/Library/Developer/Xcode/DerivedData
  2. Clean your current build by pressing ⌘⇧K
  3. Build your project
  4. In storyboard go to Editor menu and do Refresh All Views; wait for build to be completed and errors should be gone

我不需要执行第 4 步来解决问题(并让我的 PaintCode-drawRect'd UIView 在故事板中绘制),以防万一。

感谢@Mojtaba 和@WeZZard

对我来说,不是使用 #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)在设计时感知 运行。

我是如何调试和发现这个的

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

然后你会在正确的位置坠毁

就我而言,如您所见,initXXXX 正在执行一个 assert,它在设计时崩溃了,因为它正在我的 Bundle 中的文件中寻找一个值——它是 Xcode,在设计时。

只需在另一个 Xcode 安装系统上重新打开一个代码。在我的例子中它起作用了。

我为此浪费了一整天,终于解决了我的问题

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

在任何 class 标记为@IBDesignable 的地方使用 UIImage 时,我发现了一些非常重要的东西。 classic UIImage init 会使代理崩溃:

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

解决方法是使用UIImage的这个初始化方法:

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

其中 self 是您的 class 和 @IBDesignable 关键字。 Xcode9.4,Swift4.1

XCode10,Swift4.2

我找到了答案here

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

    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)