Swift--XIB nesting does not display the problem

When doing xib operations, there are often problems that the nesting of xibs is not displayed, as shown in the following sketch: MyView is dragged out by Xib, and the same is true for SubView. The left Class in MyView: Enter SubView, and enter the left in SubView SubView, this is in line with the usual idea, but it will not display your SubView when running. This causes the problem of nested Xib not showing. Solution:

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)
    }

Drag XibNestableView.Swift into the project file, the content of the file is:

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)
        }
    }
}

Drag the NibLoadable.Swift file into the project, the content is:

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
    }
}

The function of the NibLoadable.Swift protocol is to create View in the original way:

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

change into:

let alertView = BatchCloseAlertView.loadFromNib()

Insert picture description here

Guess you like

Origin blog.csdn.net/SoftwareDoger/article/details/102794121