mbogh / NibDesignable

Elegant way of enabling IBDesignable on your nib-based views
MIT License
342 stars 74 forks source link

FilesOwner as CustomView #18

Open semireg opened 8 years ago

semireg commented 8 years ago

Some developers take issue with setting FilesOwner to a UIView subclass. Is there any way around this to make NibDesignable more palatable to purists?

mbogh commented 8 years ago

I would like that too, I find it rather inconvenient that a user of NibDesignable needs to subclass it but I currently do not know of a way to "inject" the nib without subclassing.

If you have some ideas please let me know :)

thebarndog commented 8 years ago

I know how to inject the nib with keeping the base class as UIView. It's a little confusing but it follows this general process:

  1. In your nib file, set the File Owner to your custom class
  2. Wrap all your subviews in a UIView and make an outlet for that view called contentView.
  3. Override awakeFromNib to do this:
override func awakeFromNib() {
        super.awakeFromNib()
        // Load the nib into `self`. This makes self the owner and all the `IBOutlets` will be populated
        // BUT `self` will have no subviews.
        NSBundle.mainBundle().loadNibNamed("TakeVideoView", owner: self, options: nil)
        self.contentView.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(self.contentView) // add the content view as a subview (which contains all other views)

        // set all the constraints on the content view
        self.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1, constant: 0))
        self.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: .Right, relatedBy: .Equal, toItem: self, attribute: .Right, multiplier: 1, constant: 0))
        self.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: 0))
        self.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1, constant: 0))
        self.configureViews() // setup function
    }

I know that you have to set the class on Files Owner and once I figure a way around that I'll comment here but this method of nib injection is really useful for say, putting nibs in storyboards. The storyboard will first load the class of the custom view (it'll have no nib attached at this point), the view will attach the nib to itself, and add all the subviews. It's great for nib reusability.

farzadshbfn commented 7 years ago

How about using POP or Method swizzling? I think it's possible to inject the nib, instead of subclassing it this way...