GoGreen GoGreen - 1 month ago 19
Swift Question

@IBDesignable - view not rendering as expected

I have a custom

UIView
subclass that I am trying to render using
@IBDesignable
.

I have an
@IBInspectable
property named
image
, which I set from the interface builder.

When I open the interface builder the
image
that I choose is not rendered properly in the view, that is, it looks like some trouble with autolayout.
When I checked the
Report navigator
I am getting a warning in the
Interface Builder
group.

Showing All Messages
(null): -pie being ignored. It is only used when linking a main executable


This happens under the
Link <IBDESIGNABLE_EXECUTABLE>
section.

I have no idea how to fix this. Tried many solutions from SO. Cleaning build folder, clearing derived data etc. Nothing worked.

Please provide your valuable comments or a solution to this problem. Thanks! :)

EDIT:

Thanks to @Rob I could zero in to the problem.

What I have:


An
IBDesignable
UIView
Subclass with properties:


  • an
    @IBInspectable
    property named
    image
    .

  • an ImageView

  • a ScrollView



I initialise and add the ScrollView and ImageViews as subviews using

required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialiseImageView()
}

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


Problem:

In
initialiseImageView()
:

I add the
scrollView
as subview of the
UIView
and
ImageView
as the subview of the
scrollView
to use the
viewForZooming
delegate. I also add constraints to keep the views in place.

The problem is when I use:

self.translatesAutoresizingMaskIntoConstraints = false


If I use this I get autolayout warnings at runtime. But the
imageView
is misplaced in
interface builder
, although the image is rendered correctly.



If I comment the same, everything is as expected in
interface builder
. But the UI breaks at runtime due to
AutoresizingMaskIntoConstraints
.




I have the code in github. I am trying the latter approach mentioned in TN2154

I am setting all
AutoresizingMaskIntoConstraints
to be false and adding the constraints for the subviews in the code itself. The constraints for the
UIView
subclass are added in the interface builder directly and no warnings exist as of now. The code works as expected at runtime also. The
IBDesignable
part is the one that is not working as expected.




Strangely enough, When I removed the line

self.translatesAutoresizingMaskIntoConstraints = false


everything is working perfectly. The error that I used to get at runtime is now gone. I don't know if something else that I did fixed it. Thanks a lot for helping to pin point the issue @Rob.

Rob Rob
Answer

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