LoginSignup
3
1

More than 5 years have passed since last update.

【Swift4】Bundle.mainは@IBDesignableでは動作しない

Last updated at Posted at 2017-11-19

しばらく@IBDesignableで宣言したUIView+xibをXCodeに表示しない理由が分からなかったので、メモしておきます。

xibとセットで作成したUIViewを部品化して、StoryBoard上のUIViewControllerなどに貼り付けた場合、
UIViewを@IBDesignableで宣言してXCodeで表示させると思います。
この場合はちょっとしたトリックが必要で、次にあげるようなxibをロードしてUIViewに貼り付ける等な実装が必要です。

下記は部品化したいUIView+xibを@IBDesignableで表示する場合に便利な親クラスの記述です。

Swift

import UIKit

class ChildView: UIView
{
    override init(frame: CGRect)
    {
        super.init(frame: frame)
        makeView()
    }

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

    private func makeView()
    {
        let xibView: UIView? = loadNib()
        if let _xivView = xibView
        {
            addSubview(_xivView)
            addConstraint(toChildView: _xivView)  // <-- UIView+Constraint
        }
    }

    // Xibをロードする
    private func loadNib() -> UIView?
    {
        //let xibView: UIView?  = Bundle.main.loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView
        let xibView: UIView?  = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView
        return xibView
    }

    func addConstraint(toChildView childView:UIView)
    {
        childView.translatesAutoresizingMaskIntoConstraints = false;

        self.addConstraints([NSLayoutConstraint(item: childView, attribute:.top, relatedBy:.equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0),
                             NSLayoutConstraint(item: childView, attribute:.bottom, relatedBy:.equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0),
                             NSLayoutConstraint(item: childView, attribute:.left, relatedBy:.equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0),
                             NSLayoutConstraint(item: childView, attribute:.right, relatedBy:.equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0)])
    }
}

ところで、loadNib()ですが、

Swift
let xibView: UIView?  = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView

は動作しますが、

Swift
let xibView: UIView?  = Bundle.main.loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView

では動作しません。つまり、Bundle.mainは@IBDesignableでは利用できないと思われます。
XCode上でエラーが発生します。Buildするとちゃんと動作するので、@IBDesignableの(Xcode用のBuildの問題でしょう。
シングルトンのインスタンス化が@IBDesignableでは利用できないのかもしれませんが、十分な調査はできていません。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1