@ IBDesignable 崩溃代理

当我编写自己的 UIButton扩展类并将其改为 @IBDesignable时,我会收到两个 Interface Builder 错误,即:

  • Storyboard: error: IB Designables: 未能更新自动布局状态: 代理因 fd 关闭而崩溃
  • Storyboard: error: 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 中运行)

35413 次浏览

Xcode's Interface Builder requires that you implement both or neither initializers for @IBDesignable classes to render properly in IB.

If you implement required init(coder aDecoder: NSCoder) you'll need to override init(frame: CGRect) as well, otherwise "the agent will crash" as seen in the errors thrown by Xcode.

To do so add the following code to your class:

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

There are a myriad of problems that can cause this. Fire up Console, and look for the crash report IBDesignablesCocoaTouch...

I just sorted out a problem with a 3rd party designable which had issues with the valueForKey semantics.

I've met the same problem and solved it this way:

  1. The Problem:

error: IB Designables: Failed to update auto layout status: The agent crashed

  1. Find the debug button in the inspection file and click it.

debug

  1. Then the Xcode will tell you where the prolem is. In my case I drop the IBDesignable before the class.

  2. Then I clean and rebuild it, the error disappeared

This is how I solves this problem:

  • Make sure the outlets are properly initialized
  • @IBInspectable properties would be properly initialized
  • in xib file, click on File's owner placeholder, Go to Identity inspector, make sure it wont have any default values

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
}
    

    

}

Usage:

enter image description here

In Xcode 7.3, none of the above solutions worked for me, but the accepted answer to this question did: 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

I did not need to do the 4th step to solve the problem (and get my PaintCode-drawRect'd UIView to paint in the storyboard), included here just in case.

Credit to @Mojtaba and @WeZZard

For me, it was not using #if !TARGET_INTERFACE_BUILDER that got me. Basically I had some code that would result in accessing a path in my Bundle...

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

The problem is that when running in IB (and not in your app), Bundle.main isn't your app...

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

So the answer to this is simply to review your @IBDesignable UIView code carefully and use #if !TARGET_INTERFACE_BUILDER for anything (in my case calls to CoreLocation for example) that doesn't make sense when running at design time.

How I debugged and found this

This is what you see when using the Editor -> Debug Selected View while selecting your @IBDesignable UIView in your storyboard:

This is what you see when using the <code>Editor -> Debug Selected View</code> while selecting your <code>@IBDesignable UIView</code> in your storyboard

You'll then crash at the right location

The Debug Navigator

In my case, as you can see initXXXX was doing an assert, which was crashing at design time, because it was looking for a value in file in my Bundle — which is Xcode, at design time.

Just re-open a code on another Xcode setup System. In my case it Worked.

I wasted a full day on this and finally I got my problem solved enter image description here

I selected Build for target as 8.0 and it fixes everything for me.

I found something really important when using an UIImage in any class marked @IBDesignable. The classic UIImage init would crash the agent:

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

The solution is to use this init method of UIImage:

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

Working code example:

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

Where self is your class with the @IBDesignable keyword. Xcode 9.4, Swift 4.1

XCode 10, Swift 4.2

I found an answer here

Solution was simple - changing the way the bundle was resolved in the required init?(coder aDecoder: NSCoder) method of my custom view class.

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

needed to be changed to

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