在 Swift 中从笔尖加载 UIView [英] Load a UIView from nib in Swift

查看:34
本文介绍了在 Swift 中从笔尖加载 UIView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的 Objective-C 代码,我用它来为我的自定义 UIView 加载笔尖:

Here is my Objective-C code which I'm using to load a nib for my customised UIView:

-(id)init{

    NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"myXib" owner:self options:nil];
    return [subviewArray objectAtIndex:0];

}

Swift 中的等效代码是什么?

What is the equivalent code in Swift?

推荐答案

原始解决方案

  1. 我创建了一个 XIB 和一个名为 SomeView 的类(对方便性和可读性).我都基于 UIView.
  2. 在 XIB 中,我将文件所有者"类更改为 SomeView(在身份检查器中).
  3. 我在 SomeView.swift 中创建了一个 UIView 插座,将其链接到 XIB 文件中的顶级视图(为方便起见,将其命名为视图").然后,我根据需要向 XIB 文件中的其他控件添加了其他插座.
  4. 在 SomeView.swift 中,我在带代码的初始化"初始化程序中加载了 XIB.没有必要为自我"分配任何东西.加载 XIB 后,所有插座都已连接,包括顶层视图.唯一缺少的是将顶视图添加到视图层次结构中:

.

class SomeView: UIView {
   required init(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
      NSBundle.mainBundle().loadNibNamed("SomeView", owner: self, options: nil)
      self.addSubview(self.view);    // adding the top level view to the view hierarchy
   }
   ...
}

请注意,通过这种方式,我得到了一个从 nib 加载自身的类.然后,只要可以在项目中使用 UIView(在界面构建器中或以编程方式),我就可以将 SomeView 作为一个类使用.

Note that this way I get a class that loads itself from nib. I could then use SomeView as a class whenever UIView could be used in the project (in interface builder or programmatically).

更新 - 使用 Swift 3 语法

在下面的扩展中加载一个 xib 被写成一个实例方法,然后可以被上面的初始化器使用:

Loading a xib in the following extension is written as an instance method, which can then be used by an initializer like the one above:

extension UIView {

    @discardableResult   // 1
    func fromNib<T : UIView>() -> T? {   // 2
        guard let contentView = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? T else {    // 3
            // xib not loaded, or its top view is of the wrong type
            return nil
        }
        self.addSubview(contentView)     // 4
        contentView.translatesAutoresizingMaskIntoConstraints = false   // 5 
        contentView.layoutAttachAll(to: self)   // 6 
        return contentView   // 7
    }
}

  1. 使用可丢弃的返回值,因为当所有出口都已连接时,调用者对返回的视图几乎不感兴趣.
  2. 这是一个通用方法,它返回一个 UIView 类型的可选对象.如果加载视图失败,则返回 nil.
  3. 正在尝试加载与当前类实例同名的 XIB 文件.如果失败,则返回 nil.
  4. 将顶级视图添加到视图层次结构中.
  5. 这一行假设我们使用约束来布局视图.
  6. 此方法添加顶部、底部、前导和尾随约束 - 在所有方面将视图附加到self"(参见:https://stackoverflow.com/a/46279424/2274829 详情)
  7. 返回顶层视图

调用者方法可能如下所示:

And the caller method might look like this:

final class SomeView: UIView {   // 1.
   required init?(coder aDecoder: NSCoder) {   // 2 - storyboard initializer
      super.init(coder: aDecoder)
      fromNib()   // 5.
   }
   init() {   // 3 - programmatic initializer
      super.init(frame: CGRect.zero)  // 4.
      fromNib()  // 6.
   }
   // other methods ...
}

  1. SomeClass 是一个 UIView 子类,它从 SomeClass.xib 文件加载其内容.final"关键字是可选的.
  2. 在故事板中使用视图时的初始化程序(请记住使用 SomeClass 作为故事板视图的自定义类).
  3. 用于以编程方式创建视图时的初始化程序(即:let myView = SomeView()").
  4. 使用全零框架,因为此视图是使用自动布局布局的.请注意,init(frame: CGRect) {..}"方法不是独立创建的,因为我们的项目中专门使用了自动布局.
  5. &6. 使用扩展名加载 xib 文件.

信用:在此解决方案中使用通用扩展的灵感来自 Robert 在下面的回答.

Credit: Using a generic extension in this solution was inspired by Robert's answer below.

编辑将view"更改为contentView"以避免混淆.也将数组下标改为.first".

Edit Changing "view" to "contentView" to avoid confusion. Also changed the array subscript to ".first".

这篇关于在 Swift 中从笔尖加载 UIView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆