IntrepidPursuits / swift-wisdom

A collection of additions to the Swift Standard Library created by Intrepid Pursuits developers
MIT License
39 stars 14 forks source link

Added 'NibLoadableView' for easier loading of Nibs into placeholder Views. #118

Closed chow-land closed 7 years ago

chow-land commented 7 years ago

Subclassing NibLoadableView allows you to automate the loading of a Nib into a placeholder view inside another Nib, using only the Custom Class attribute.

It removes the need to perform the following manual steps every time you want a Nib that can load into a placeholder View:

YourCustomView: NibLoadableView {}

brightredchilli commented 7 years ago

seems like

 guard let topLevelObjects = Bundle.main.loadNibNamed(self.customClassString, owner: self, options: nil)

~would do it, where customClassString is an ibdesignable of type String.~ I got it...give me a think

chow-land commented 7 years ago

@brightredchilli Also, as a separate note, I tried another approach where instead of subclassing UIView I tried to make a UIView extension that made all UIViews conform to a NibLoadable protocol. Then I made a default implementation of init(withCoder:) in an extension of NibLoadable - but I found that the init(withCoder:) on the extension would never actually fire. I think this is by design and Apple only allows you to override methods via subclassing, so that's why I ended up going the subclass route.

chow-land commented 7 years ago

@brightredchilli I just had another thought.

How about instead of subclassing, I just expose this as an extension method on UIView, and leave it up to the developer to call it in initWithCoder.

E.g.:

extension UIView {
   func loadCompanionNibAndConstrainToContainer() {..}
}

class SomeView : UIView {
   init(coder aDecoder: NSCoder) {
         super.init(coder: aDecoder)
         self.loadCompanionNibAndConstrainToContainer()
      }
}

This way it would be a little more explicit what's actually happening, and you wouldn't need to subclass a special type. There would still be the redundant view level in the hierarchy, but I see that as a small price to pay for having the ability to use IBDesignable.

chow-land commented 7 years ago

Some background on how we can get IBDesignable working with a view that has a backing nib, i.e. how to live render a nib inside interface builder: http://justabeech.com/2014/07/27/xcode-6-live-rendering-from-nib/

Going to work on this a bit more.

brightredchilli commented 7 years ago

i love the idea of not having two instances of the custom view, and that looks promising.

brightredchilli commented 7 years ago

I have a hunch this might work, but having the two references is kind of ugly too:

class ViewController: UIViewController {

    @IBOutlet var container: NibLoadableView!
    lazy var myCustomView: CustomView {
        return container.getInnerView()
    }
}

class NibLoadableView : UIView {

  // initialization blah blah
    func getInnerView() -> T {
        return topLevelView as! T
    }
}
ghost commented 7 years ago

SonarQube analysis reported 2 issues

Watch the comments in this conversation to review them.

ghost commented 7 years ago
4 Warnings
:warning: Array+UtilitiesTests.swift#L100 - SwiftWisdomTests/StandardLibrary/Array/Array+UtilitiesTests.swift#L100: ‘subscript(ip_safe:)’ is deprecated: Use ip_safely instead.
XCTAssert(testArray[ip_safe: 3] == 4)
:warning: Array+UtilitiesTests.swift#L101 - SwiftWisdomTests/StandardLibrary/Array/Array+UtilitiesTests.swift#L101: ‘subscript(ip_safe:)’ is deprecated: Use ip_safely instead.
XCTAssert(testArray[ip_safe: 8] == 9)
:warning: Array+UtilitiesTests.swift#L102 - SwiftWisdomTests/StandardLibrary/Array/Array+UtilitiesTests.swift#L102: ‘subscript(ip_safe:)’ is deprecated: Use ip_safely instead.
XCTAssertNil(testArray[ip_safe: -1])
:warning: Array+UtilitiesTests.swift#L103 - SwiftWisdomTests/StandardLibrary/Array/Array+UtilitiesTests.swift#L103: ‘subscript(ip_safe:)’ is deprecated: Use ip_safely instead.
XCTAssertNil(testArray[ip_safe: 9])
1 Message
:book: Executed 142 tests, with 0 failures (0 unexpected) in 0.239 (0.296) seconds

Generated by :no_entry_sign: Danger