I very rarely override drawRect in my UIView subclasses, usually preferring to set layer.contents
with pre-rendering images and often employing multiple sublayers or subviews and manipulating these based on input parameters. Is there a way for IB to render these more complex view stacks?
相关问题
- CALayer - backgroundColor flipped?
- Core Data lightweight migration crashes after App
- “Zero out” sensitive String data in Swift
- back button text does not change
- SwiftUI: UIImage (QRCode) does not load after call
相关文章
- 现在使用swift开发ios应用好还是swift?
- Using if let syntax in switch statement
- TCC __TCCAccessRequest_block_invoke
- xcode 4 garbage collection removed?
- Xcode: Is there a way to change line spacing (UI L
- Unable to process app at this time due to a genera
- Enum with associated value conforming to CaseItera
- Swift - hide pickerView after value selected
This answer is related to overriding drawRect, but maybe it can give some ideas:
I have a custom UIView class which has complex drawings in drawRect. You have to take care about references which are not available during design time, i.e. UIApplication. For that, I override
prepareForInterfaceBuilder
where I set a boolean flag which I use in drawRect to distinguish between runtime and design time:An here is how it looks in InterfaceBuilder:
In my case, there were two problems:
I did not implement
initWithFrame
in custom view: (UsuallyinitWithCoder:
is called when you initialize via IB, but for some reasoninitWithFrame:
is needed forIBDesignable
only. Is not called during runtime when you implement via IB)My custom view's nib was loading from
mainBundle
:[NSBundle bundleForClass:[self class]]
was needed.Swift 3 macro
and class with function which is called when IB renders storyboard
IBInspectable can be used with types below
You do not have to use drawRect, instead you can create your custom interface in a xib file, load it in initWithCoder and initWithFrame and it will be live rendering in IB after adding IBDesignable. Check this short tutorial: https://www.youtube.com/watch?v=L97MdpaF3Xg
To elaborate upon Hari Karam Singh's answer, this slideshow explains further:
http://www.splinter.com.au/presentations/ibdesignable/
Then if you aren't seeing your changes show up in Interface Builder, try these menus:
Unfortunately, debugging my view froze Xcode, but it should work for small projects (YMMV).
Thanks, @zisoft for the clueing me in on
prepareForInterfaceBuilder
. There a few nuances with Interface Builder's render cycle which were the source of my issues and are worth noting...-drawRect
.Setting images on UIButton control states works. Arbitrary layer stacks seem to work if a few things are kept in mind...
initWithFrame:
..not
initWithCoder
.awakeFromNib
is also NOT called.init...
is only called once per sessionI.e. once per re-compile whenever you make a change in the file. When you change IBInspectable properties, init is NOT called again. However...
prepareForInterfaceBuilder
is called on every property changeIt's like having KVO on all your IBInspectables as well as other built-in properties. You can test this yourself by having the your
_setup
method called, first only from yourinit..
method. Changing an IBInspectable will have no effect. Then add the call as well toprepareForInterfaceBuilder
. Whahla! Note, your runtime code will probably need some additional KVO since it won't be calling theprepareForIB
method. More on this below...init...
is too soon to draw, set layer content, etc.At least with my
UIButton
subclass, calling[self setImage:img forState:UIControlStateNormal]
has no effect in IB. You need to call it fromprepareForInterfaceBuilder
or via a KVO hook.Can be confusing at times when you are making changes that have no effect. Check the build logs.
Tip: Keep Activity Monitor nearbyI get hangs all the time on a couple different support processes and they take the whole machine down with them. ApplyForce Quit
liberally.(UPDATE: This hasn't really been true since XCode6 came out of beta. It seldom hangs anymore)
UPDATE
prepareForInterfaceBuilder
method effectively KVOs all theIBInspectable
properties. It's unfortunate that this behaviour isn't mirrored somehow at runtime thus requiring the manual KVO. See the updated sample code below.UIButton subclass example
Below is some example code of a working IBDesignable
UIButton
subclass. ~~Note,prepareForInterfaceBuilder
isn't actually required as KVO listens for changes to our relevant properties and triggers a redraw.~~ UPDATE: See point 8 above.