@IBDesignable - view not rendering as expected
BTW, I just did a quick @IBDesignable
with an @IBInspectable
that was a UIImage
and a draw(rect:)
that rendered that image and it worked fine:
@IBDesignable class CustomView: UIView {
@IBInspectable var image: UIImage?
override func draw(_ rect: CGRect) {
image?.draw(at: CGPoint.zero)
}
}
When I do that in a separate target (as one should with designables), I also see the same warning:
ld: warning: -pie being ignored. It is only used when linking a main executable
I suspect that warning may be a red herring. The man
pages for ld
described -pie
option as follows:
This makes a special kind of main executable that is position independent (PIE).
You can toggle this setting if you go to the link settings for your designables' target and change the "Generate Position-Dependent Executable" in the "Linking" settings. Then that warning will go away. Personally, I've never noticed that warning and never changed this settings, and never noticed any adverse affects, but if you want to confirm this for your own sense of satisfaction, try changing this setting and see if you can get the warning to go away.
Bottom line, your @IBDesignable
problem probably rests elsewhere, but it's hard to diagnose on the basis of the information provided. We need more information (or, ideally, a MCVE).
It's hard to comment on your autolayout warnings without seeing what those warning are, but I'd guess that (a) you're adding a subview; but (b) not setting the constraints for said subview; and therefore (c) that when you set translatesAutoresizingMaskIntoConstraints = false
, that your constraints are ambiguous and therefore result in error messages and unexpected layout at runtime. Or maybe it's a symptom of the idiosyncrasies of scroll views. But it's hard to say without seeing (a) actual autolayout error; (b) what subviews your @IBDesignable
added; and (c) what constraints you added for your subviews.
Bottom line, make sure that your programmatically added subviews have all of their constraints unambiguously defined. Also remember that constraints for scrollview subviews act differently that many constraints, defining the contentSize of the scroll view rather than the size of the subviews. (On this latter point, see TN2154.)
IBDesignable View Rendering times out
Apparently I needed to override init(frame: CGRect)
along with init(code: NSCoder)
.
Got it working! If anyone could care to explain why this wasn't working, that would be great. Otherwise, I'm fine here.
IBDesignable View with Dynamic Constraints: Misplaced Children when Rendering
Do not set translatesAutoresizingMaskIntoConstraints = false
for your Designable view itself.
let views = ["placeholder": placeholder, "choice": choiceImage]
// don't do this one
//translatesAutoresizingMaskIntoConstraints = false
placeholder.translatesAutoresizingMaskIntoConstraints = false
choiceImage.translatesAutoresizingMaskIntoConstraints = false
addSubview(placeholder)
addSubview(choiceImage)
Also, to see your "choice" image in IB:
let theBundle = Bundle(for: type(of: self))
let choiceImage = UIImageView(image: UIImage(named: "plus_small", in: theBundle, compatibleWith: self.traitCollection))
//
//let choiceImage = UIImageView(image: UIImage(named: "plus_small"))
...
view.frame is not set when IBDesignable loads xib
You should move any size related adjustments into layoutSubviews
. This way, not only will it be rendered correctly in IB, but also on device, if the size of the window changes, the cornerRadius
will be adjusted accordingly.
@IBDesignable view doesn't draw background color inside Interface Builder
While rendering in Interface builder(IB), the properties which are set in IB of custom UI element are loaded after the call to init
. Your code for setting the backgroundColor
in init
is getting called. But after that, it again sets the backgroundColor
for the value of backgroundColor
in IB.
I could not find the Apple documentation for this. I am saying this based on following analysis. I modified your code a little for debugging.
@IBDesignable class CustomLabel: UIView {
let view = UIView()
override var backgroundColor: UIColor? {
didSet {
print("here: "); // break point 1
}
}
func setup() {
self.backgroundColor = UIColor.redColor() // break point 2
view.backgroundColor = UIColor.greenColor()
view.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
addSubview(view)
}
override init(frame: CGRect) {
super.init(frame: frame) // break point 3
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) // break point 4
setup()
}
}
Now, put the breakpoints in all methods. Then, select the object of CustomLabel
in Interface Builder, and choose Editor ➔ Debug Selected Views.
You can see the sequence of method calls. This just shows the sequence of rendering in interface builder, not the sequence it may follow in run time.
May be you know this, but for the sake of clarity, you can use following to reflect this in IB.
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
backgroundColor = UIColor.grayColor()
}
xcode 6 IB_DESIGNABLE- not loading resources from bundle in Interface builder
As of when this question was first asked, creating an IB-designable control required packaging it in a framework target. You don't have to do that anymore — the shipping Xcode 6.0 (and later) will preview IB-designable controls from your app target, too. However, the problem and the solution are the same.
Why? [NSBundle mainBundle]
returns the primary bundle of the currently running app.
When you call that from a framework, you're getting a different bundle returned based on which app is loading your framework. When you run your app, your app loads the framework. When you use the control in IB, a special Xcode helper app loads the framework. Even if your IB-designable control is in your app target, Xcode is creating a special helper app to run the control inside of IB.
The solution? Call +[NSBundle bundleForClass:]
instead (or NSBundle(forClass:)
in Swift). This gets you the bundle containing the executable code for whichever class you specify. (You can use [self class]
/self.dynamicType
there, but beware the result will change for subclasses defined in different bundles.)
If you're using the framework approach — which can be useful for some apps even though it's no longer required for IB-designable controls — it's best to put image resources in the same framework with the code that uses them. If your framework code expects to use resources provided at run time by whatever app loads the framework, the best thing to do for making it IB-designable is to fake it. Implement the prepareForInterfaceBuilder
method in your control and have it load resources from a known place (like the framework bundle or a static path in your Xcode workspace).
Related Topics
Convenience Initialization of Uinavigationcontroller Subclass Makes Subclass Constant Init Twice
My Uiviews Muck-Up When I Combine Uipangesturerecognizer and Autolayout
Use More Than One Firebase Database in Single App - Swift
How to Retrieve Image Stored in Firebase to Show It in View Image View
Manage a Uipickerview from an External Class - Using Swift
How to Keep the Header Cell Moving with the Tableview Cells in Swift 2.0
Wkwebview Blank After 'Successful' Https Nsurlrequest
7 Duplicate Symbols for Architecture X86_64 in React Native
Swift Add Line Above to Control
Cmpedometer Querypedometerdatafromdate Returns Error 103
Turning on Thread Sanitizer Results in Signal Sigabrt
How to Perform Realm Count Query
iOS Healthkit How to Save Heart Rate (Bpm) Values? Swift
Get Current Song Playing in Spotify on Iphone
Uitapgesturerecognizer Sender Is the Gesture, Not the UI Object