Swift--XIB 嵌套不显示的问题

进行xib作业的时候常常会出现xib嵌套不显示的问题,如下面草图所示: MyView是Xib拖出来的,SubView也同样是,MyView中的左侧Class:输入SubView,在SubView中左侧输入SubView,这符合一贯的思路,但是运行起来不会显示你的SubView,这就出现了嵌套Xib不显示的问题,解决思路:

1.在SubView.Xib文件中,右侧导航栏Class:不填,保持原来的类型,在Placeholder--File's Owner下修改Class:SubView
2.在SubView.Swift文件中 ,SubView遵守一个自己封装的协议XibNestableView,如下:class SubView: XibNestableView {},  初始化方法为:
required init?(coder aDecoder: NSCoder) {
    
    
        super.init(coder: aDecoder)
    }

XibNestableView.Swift 拖入到工程文件中,文件内容为:

import UIKit
/// Xib 嵌套 Nib 所需继承的 View
class XibNestableView : UIView , NibLoadable {
    
        
    required init?(coder aDecoder: NSCoder) {
    
    
        super.init(coder: aDecoder)
        if let view = UINib(nibName: String(describing: type(of: self)), bundle: nil).instantiate(withOwner: nil, options: nil)[0] as? UIView {
    
    
            view.equal(to: self)
        }
    }
}

NibLoadable.Swift文件拖入工程中,内容为:

import UIKit

/// 标志符协议
protocol NameIdentifierable {
    
    }

extension NameIdentifierable {
    
    
    /// 将类型名称作为标识符字符串
    static var identifier: String {
    
    
        return String(describing: self)
    }
}

/// 加载 Xib 协议
protocol NibLoadable: NameIdentifierable {
    
    }

extension NibLoadable where Self : AnyObject {
    
    
    /// 加载 Xib 中的 Nib 文件,Xib文件名称需与类型名称相同
    static var nib: UINib {
    
    
        return UINib(nibName: identifier, bundle: Bundle(for: self))
    }
}

extension NibLoadable where Self: UIView {
    
    
    
    /// 从 Nib 文件中加载 View
    ///
    /// - Returns: 实现 NibLoadable 的 UIView
    /// 例子: let view = UIView.loadFromNib()
    static func loadFromNib() -> Self {
    
    
        guard let view = nib.instantiate(withOwner: nil, options: nil).first as? Self else {
    
    
            fatalError("\(nib) Nib 文件的根视图需为 \(self) 类型")
        }
        return view
    }
}

protocol NibOwnerLoadable : NameIdentifierable {
    
    }

extension NibOwnerLoadable where Self : AnyObject {
    
    
    
    /// 加载 Xib 中的 Nib 文件,Xib文件名称需与类型名称相同
    static var nib: UINib {
    
    
        return UINib(nibName: identifier, bundle: Bundle(for: self))
    }
}

extension NibOwnerLoadable where Self: UIView {
    
    
    
    
    /// 加载 File’s Owner 中的内容
    /// 例子: required init?(coder aDecoder: NSCoder) {
    
    
    ///         super.init(coder: aDecoder)
    ///         self.loadNibContent()
    ///       }
    func loadNibContent() {
    
    
        let layoutAttributes: [NSLayoutConstraint.Attribute] = [.top, .leading, .bottom, .trailing]
        for case let view as UIView in Self.nib.instantiate(withOwner: self, options: nil) {
    
    
            view.translatesAutoresizingMaskIntoConstraints = false
            self.addSubview(view)
            NSLayoutConstraint.activate(layoutAttributes.map {
    
     attribute in
                NSLayoutConstraint(
                    item: view, attribute: attribute,
                    relatedBy: .equal,
                    toItem: self, attribute: attribute,
                    multiplier: 1, constant: 0.0
                )
            })
        }
    }
}

/// 加载 Storyboard 协议
protocol StoryboardLoadable {
    
    
    
    /// 需要加在的 Storyboard 的名字
    static var storyboardName: String? {
    
     get }
}

extension StoryboardLoadable where Self : AnyObject, Self : NameIdentifierable {
    
    
    
    /// 创建与 storyboardName 相同的 Storyboard, 若 storyboardName 为空则创建与当前类型名字相同的 Storyboard
    static var storyboard: UIStoryboard {
    
    
        return UIStoryboard(name: storyboardName ?? identifier, bundle: Bundle(for: self))
    }
}

/// Storyboard 中的控制器加载协议
protocol StoryboardSceneLoadable : NameIdentifierable {
    
    
   
    /// 需要提供目标 Storyboard, 可通过 StoryboardLoadable 协议创建
    static var storyboard: UIStoryboard {
    
     get }
}

extension StoryboardSceneLoadable {
    
    
    
    /// ViewController 的标志符
    static var sceneIdentifier: String {
    
    
        return identifier
    }
}

extension StoryboardSceneLoadable where Self: UIViewController {
    
    
    //
    /// 从 storyboard 中加载标志为 sceneIdentifier 的 ViewController
    ///
    /// - Returns: 标志为 sceneIdentifier 的 ViewController
    static func instantiate() -> Self {
    
    
        let storyboard = Self.storyboard
        let viewController = storyboard.instantiateViewController(withIdentifier: self.sceneIdentifier)
        guard let typedViewController = viewController as? Self else {
    
    
            fatalError("\(storyboard) 中的 '\(self.sceneIdentifier)'控制器不是 '\(self)' 类型")
        }
        return typedViewController
    }
}

NibLoadable.Swift 协议的作用是将创建View由原来的方式:

let alertView = Bundle.main.loadNibNamed("BatchCloseAlertView", owner: vc, options: nil)?.first as! BatchCloseAlertView

修改为:

let alertView = BatchCloseAlertView.loadFromNib()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/SoftwareDoger/article/details/102794121