I want to use a view throughout multiple viewcontrollers in a storyboard. Thus, I thought about designing the view in an external xib so changes are reflected in every viewcontroller. But how can one load a view from a external xib in a storyboard and is it even possible? If thats not the case, what other alternatives are availble to suit the situation abouve?
相关问题
- Core Data lightweight migration crashes after App
- How can I implement password recovery in an iPhone
- State preservation and restoration strategies with
- “Zero out” sensitive String data in Swift
- Get the NSRange for the visible text after scroll
相关文章
- 现在使用swift开发ios应用好还是swift?
- UITableView dragging distance with UIRefreshContro
- TCC __TCCAccessRequest_block_invoke
- Where does a host app handle NSExtensionContext#co
- Swift - hide pickerView after value selected
- How do you detect key up / key down events from a
- “Storyboard.storyboard” could not be opened
- didBeginContact:(SKPhysicsContact *)contact not in
Solution for Objective-C according to steps described in Ben Patch's response.
Use extension for UIView:
Create files
MyView.h
,MyView.m
andMyView.xib
.First prepare your
MyView.xib
as Ben Patch's response says so set classMyView
for File's owner instead of main view inside this XIB.MyView.h
:MyView.m
:And later just create your view programatically:
Warning! Preview of this view will not be shown in Storyboard if you use WatchKit Extension because of this bug in Xcode >= 9.2: https://forums.developer.apple.com/thread/95616
I've always found the "add it as a subview" solution unsatisfactory, seeing as it screws with (1) autolayout, (2)
@IBInspectable
, and (3) outlets. Instead, let me introduce you to the magic ofawakeAfter:
, anNSObject
method.awakeAfter
lets you swap out the object actually woken up from a NIB/Storyboard with a different object entirely. That object is then put through the hydration process, hasawakeFromNib
called on it, is added as a view, etc.We can use this in a "cardboard cut-out" subclass of our view, the only purpose of which will be to load the view from the NIB and return it for use in the Storyboard. The embeddable subclass is then specified in the Storyboard view's identity inspector, rather than the original class. It doesn't actually have to be a subclass in order for this to work, but making it a subclass is what allows IB to see any IBInspectable/IBOutlet properties.
Note: the class set on the view in the NIB file remains the same. The embeddable subclass is only used in the storyboard. The subclass can't be used to instantiate the view in code, so it shouldn't have any additional logic, itself. It should only contain the
awakeAfter
hook.⚠️ The one significant drawback here is that if you define width, height, or aspect ratio constraints in the storyboard that don't relate to another view then they have to be copied over manually. Constraints that relate two views are installed on the nearest common ancestor, and views are woken from the storyboard from the inside-out, so by the time those constraints are hydrated on the superview the swap has already occurred. Constraints that only involve the view in question are installed directly on that view, and thus get tossed when the swap occurs unless they are copied.
Note that what is happening here is constraints installed on the view in the storyboard are copied to the newly instantiated view, which may already have constraints of its own, defined in its nib file. Those are unaffected.
instantiateViewFromNib
is a type-safe extension toUIView
. All it does is loop through the NIB's objects until it finds one that matches the type. Note that the generic type is the return value, so the type has to be specified at the call site.