【Extension晒すシリーズ】UIView



import UIKit

extension UIView {

    public typealias Completion = () -> Void

    /// SubViewの一番右の座標取得
    public var maxSubViewRight: CGFloat {
        guard let view = subviews.max(by: { (a, b) in
            return a.frame.origin.x + a.frame.width <= b.frame.origin.x + b.frame.width
        }) else {
            return 0
        }
        return view.frame.origin.x + view.frame.width
    }

    /// SubViewの一番下の座標取得
    public var maxSubViewBottom: CGFloat {
        guard let view = subviews.max(by: { (a, b) -> Bool in
            return a.frame.origin.y + a.frame.height < b.frame.origin.y + b.frame.height
        }) else {
            return 0
        }
        return view.frame.origin.y + view.frame.height
    }

    /// SubViewの最大サイズ
    public var maxSubViewSize: CGSize {
        return CGSize(width: maxSubViewRight, height: maxSubViewBottom)
    }

    /// 角Radius
    @IBInspectable public var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }

    /// 枠線太さ
    @IBInspectable public var borderWidth: CGFloat {
        get {
            return self.layer.borderWidth
        }
        set {
            self.layer.borderWidth = newValue
        }
    }

    /// 枠線色
    @IBInspectable public var borderColor: UIColor? {
        get {
            return UIColor.init(cgColor: self.layer.borderColor!)
        }
        set {
            self.layer.borderColor = newValue?.cgColor
        }
    }

    /// Nibを生成
    ///
    /// - Returns: Nib
    public class func createNib() -> UINib {
        return UINib(nibName: className, bundle: Bundle(for: self))
    }

    /// Nibからロード
    /// - returns: インスタンス
    open class func loadFromNib() -> UIView {
        return createNib().instantiate(withOwner: self, options: nil)[0] as! UIView
    }

    /// Marginを指定してaddSubview
    /// - parameter view:   view
    /// - parameter top:    top margin
    /// - parameter bottom: bottom margin
    /// - parameter left:   left margin
    /// - parameter right:  right margin
    public func addSubviewWithFit(_ view: UIView, top: CGFloat = 0, bottom: CGFloat = 0, left: CGFloat = 0, right: CGFloat = 0) {
        addSubview(view)
        view.fitToParent(top: top, bottom: bottom, left: left, right: right)
    }

    /// 親にfitさせる
    /// - parameter view:   view
    /// - parameter top:    top margin
    /// - parameter bottom: bottom margin
    /// - parameter left:   left margin
    /// - parameter right:  right margin
    public func fitToParent(top: CGFloat = 0, bottom: CGFloat = 0, left: CGFloat = 0, right: CGFloat = 0) {
        guard let superview = superview else {
            return
        }
        bounds = superview.bounds
        translatesAutoresizingMaskIntoConstraints = false

        superview.addConstraints([
            NSLayoutConstraint(
                item: self,
                attribute: .left,
                relatedBy: .equal,
                toItem: superview,
                attribute: .left,
                multiplier: 1.0,
                constant: left
            ),

            NSLayoutConstraint(
                item: self,
                attribute: .top,
                relatedBy: .equal,
                toItem: superview,
                attribute: .top,
                multiplier: 1.0,
                constant: top
            ),

            NSLayoutConstraint(
                item: self,
                attribute: .right,
                relatedBy: .equal,
                toItem: superview,
                attribute: .right,
                multiplier: 1.0,
                constant: right
            ),

            NSLayoutConstraint(
                item: self,
                attribute: .bottom,
                relatedBy: .equal,
                toItem: superview,
                attribute: .bottom,
                multiplier: 1.0,
                constant: bottom
            )
            ]
        )
    }

    /// centerにaddSubView
    ///
    /// - Parameter view: view
    public func addSubViewToCenter(_ view: UIView) {
        addSubview(view)
        view.moveToParentCenter()
    }

    /// 親のcenterに配置する
    public func moveToParentCenter() {
        guard let superview = superview else {
            return
        }
        bounds = superview.bounds
        translatesAutoresizingMaskIntoConstraints = false

        superview.addConstraints([
            NSLayoutConstraint(
                item: self,
                attribute: .centerX,
                relatedBy: .equal,
                toItem: superview,
                attribute: .centerX,
                multiplier: 1.0,
                constant: 1
            ),
            NSLayoutConstraint(
                item: self,
                attribute: .centerY,
                relatedBy: .equal,
                toItem: superview,
                attribute: .centerY,
                multiplier: 1.0,
                constant: 1
            )
            ]
        )
    }

    /// フェードイン
    ///
    /// - Parameters:
    ///   - duration: 時間
    ///   - completion: 完了通知
    public func fadeIn(duration: TimeInterval, completion: Completion?) {
        fadeImpl(true, duration: duration, completion: completion)
    }

    /// フェードアウト
    ///
    /// - Parameters:
    ///   - duration: 時間
    ///   - completion: 完了通知
    public func fadeOut(duration: TimeInterval, completion: Completion?) {
        fadeImpl(false, duration: duration, completion: completion)
    }

    private func fadeImpl(_ isfadeIn: Bool, duration: TimeInterval, completion: Completion?) {
        alpha = isfadeIn ? 0 : 1
        self.layer.removeAllAnimations()
        UIView.animate(withDuration: duration, animations: {
            self.alpha = isfadeIn ? 1 : 0
        }, completion: { finished in
            if finished {
                completion?()
            }
        })
    }

    /// 子を全て削除
    public func removeAllSubView() {
        subviews.forEach { (subView) in
            subView.removeFromSuperview()
        }
    }
}