【问题标题】:Custom UIView with Nib in swift without using loadFromNib in the view controller快速使用 Nib 自定义 UIView 而无需在视图控制器中使用 loadFromNib
【发布时间】:2015-03-22 05:55:02
【问题描述】:

我一直使用 loadNibNamed 方法将自定义视图加载到视图控制器中,但现在我试图避免在自定义视图之外调用该方法以使其更可重用,这样如果其他人使用我的自定义视图,他只会将需要在没有 loadFromNib 的情况下实例化视图,例如:

var myView: MyView = MyView()

并且将此视图添加到视图控制器的视图中就足够了,自定义视图将在其内部加载 nib。 我正在尝试在 Swift 中执行此操作,在 ObjC 中我发现了类似以下答案之一的代码:UIView and initWithFrame and a NIB file. How can i get the NIB file loaded? 但是在swift中我不能使用答案中使用的init:

- (id)initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code.
        //
        [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil];
        [self addSubview:self.view];
    }
    return self;
}

我有这个方法,它以无限循环结束:

override init(frame: CGRect) {
    super.init(frame: frame)
    self.loadFromNibNamed("MyView")
}

我还尝试在 MyView 中添加另一个视图作为 IBOutlet 就像另一个答案所说的那样,并使用所有的 inits:

@IBOutlet var view: UIView!

override init() {
    super.init()
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
    self.addSubview(self.view)
}

override init(frame: CGRect) {
    super.init(frame: frame)
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
    self.addSubview(self.view)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
    self.addSubview(self.view)
}

但还是报了无限循环的错误。

我找不到一个好的解决方案,这让我发疯了!!有人可以帮助我吗?谢谢!

【问题讨论】:

  • 您的NIB 是否包含MyViewMediaPlayerView 类的视图?这可能是无限循环的原因,我猜init(coder:)是原因。

标签: ios swift uiview nib


【解决方案1】:

我认为更简洁的方法是使用默认初始化程序,而是使用您自己的初始化程序,例如像这样

override init(frame: CGRect, shouldLoadFromNib: Bool) {
    super.init(frame)
    guard shouldLoadFromNib else {
         return
    }
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
    self.addSubview(self.view)

}

这样,当您从其他地方实例化它时,您会立即看到这不仅仅是某些 UIView 的普通旧实例化,而且它有副作用(视图将从笔尖加载)

我不确定super.init(frame) 调用,loadNibNamed 可能也会为你调用,所以你可能想检查一下

【讨论】:

    【解决方案2】:

    你得到了一个无限循环,因为loadNibNamed(_,owner:,options:)调用了init,所以然后尝试再次加载笔尖,然后再次以此类推...试试这个:

    斯威夫特 4

    var contentView: UIView?
    
    // MARK: Initializers
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        configureView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configureView()
    }
    
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        configureView()
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        configureView()
    }
    
    // MARK: Config Functions
    
    func configureView() {
        guard let view = defaultView() else { return }
        view.frame = bounds
        view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        addSubview(view)
        contentView = view
    
        updateView()
    }
    
    func defaultView() -> UIView? {
        // Create view from a nib with the same name
        let nibName = String(describing: type(of: self))
        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: nibName, bundle: bundle)
    
        return nib.instantiate(withOwner: self, options: nil).first as? UIView
    }
    

    此代码的作用是从 nib 加载视图,然后将其添加到视图内的子视图中。

    这也适用于在另一个 xib 上添加您的视图时,添加 @IBDesignable 它将变为可用

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      • 1970-01-01
      • 2019-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多