- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试围绕使用 Xib 文件创建自定义 UIView
的主题进行思考。我已经做过很多次了,但我从来没有想过为什么这个过程如此复杂,哪些部分是必要的,哪些部分是好的等等。而现在,因为 Xibs 是我正在从事的项目的主要组成部分,我开始质疑一切 - 我需要确定发生了什么 😉
假设我们刚刚创建了一个简单的 UIView
子类 - 我们将其命名为 CustomView
,该类的基本要求是实现所需的初始化程序,如下所示:
class CustomView: UIView {
// This one is for initializing programmatically
override init(frame: CGRect) {
super.init(frame: frame)
}
// This one is for Storyboards and Xibs
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
当然,我们有关联的 Xib 文件,因此我们实际上要做的第一件事就是转到那里并将文件所有者设置为CustomView
。
现在,有趣的部分开始了。如果您查看许多在线可用资源( here 或 here ),每个人都会创建一个从两个初始化程序调用的 commonInit 方法,我知道这是为了在两者之间保持一致性CustomView
的初始化方法,但有点神奇的是为什么在这些方法中我们为 contentView
加载 Nib,并对其施加约束并将它作为 subview 添加到我们的类中?看看代码注释就知道了:
class CustomView: UIView {
@IBOutlet weak var contentView: UIView?
@IBOutlet weak var someSubview: UIView?
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
// Why we're loading this `contentView` from Xib?`
self.contentView = loadViewFromNib()
// Why do we have to add it when I's already added in IB?
self.addSubview(contentView)
// Why do we need a constraints for it when IB shows it's filling whole view?
self.contentView.translatesAutoresizingMaskIntoConstraints = false
let trailingAnchor = contentView.trailingAnchor.constraint(equalTo: trailingAnchor)
let leadingAnchor = contentView.leadingAnchor.constraint(equalTo: leadingAnchor)
let topAnchor = contentView.topAnchor.constraint(equalTo: topAnchor)
let bottomAnchor = contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
NSLayoutConstraint.activate([trailingAnchor, leadingAnchor, topAnchor, bottomAnchor])
}
private func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: String(self.dynamicType), bundle: bundle)
let nibView = nib.instantiateWithOwner(self, options: nil).first as! UIView
return nibView
}
}
下面是令人烦恼的问题:
contentView
? contentView
已经是 @IBOutlet
时,为什么我们还要从 Xib 文件加载它?难道不应该免费给我们吗?我想这是为了使用 init(frame:)
从代码中初始化我们的 View ,对吧? contentView
添加为 subview 并设置其约束,而 Xib 已经指定了所有内容?我还看到了上述代码的一个较短版本,没有约束,并且从 Nib 层次结构中完整加载了第一个 UIView
:
private func commonInit() {
Bundle.main.loadNibNamed(String(describing: CustomView.self), owner: self, options: nil)
guard let contentView = contentView else { return }
self.addSubview(contentView)
}
它与更详细的方法有何不同?它实际上可以与自动布局和其他一切一起正常工作吗?
最佳答案
有两种方法可以从 Nib 加载自定义 View 。您可以在 IB 中添加一个普通的 UIView 并将此 View 设置为自定义类(类似于 UITableView 子类的设置方式)。注意文件所有者在这种情况下没有被修改。当您从代码中加载 nib 时,您会直接获得一个完全可用的 UIView 子类。您有责任约束它并将其添加到 View 层次结构中。您无法从 IB 本身添加此 View ,因为您无法从 IB 加载它。
第二个是将 XIBs 文件所有者设置为自定义类。这就是 UIViewControllers 在 Storyboards 之前的设置方式。文件所有者是一个代理对象,加载时 IBOutlets 将连接到该代理对象。这支持以编程方式和 IB 本身构建,您只需要在任何 Storyboard 中放置一个自定义 UIView 并将其自定义类设置为您的 UIView 子类,您在自定义子类中添加的代码将加载 XIB 并添加其内容 View 。
直接回答你的问题:
init(nibName:bundle:)
构造函数为您完成的)translatesAutoresizingMaskIntoConstraints
创建基于与父 View 相等的框架的约束。编辑:行 self.contentView = loadViewFromNib()
是无关紧要的。您不需要分配给 contentView
(或从 loadViewFromNib
方法返回任何内容。您只需要在 XIB 文件中建立连接,它会自动设置正在加载。owner: self
参数表示您的自定义类将负责处理所有连接
关于ios - 来自 Xib 的自定义 UIView - 要求,良好实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49480436/
嗨,我正在考虑开发一种文件传输程序,想知道我是否想要尽可能好的加密,我应该使用什么? 我会用 C# 开发它,所以我可以访问 .net 库 :P在我的 usb 上有一个证书来访问服务器是没有问题的,如果
我创建的这个计算两个数组的交集是线性的方法的复杂度(在良好、平均、最差的情况下)? O(n) public void getInt(int[] a,int[] b){ int i=0; int
我已经能够使用 RTCPeerConnection.getStats() API 获得 WebRTC 音频调用的各种统计信息(抖动、RTT、丢包等)。 我需要将整体通话质量评为优秀、良好、一般或差。
基本问题: 如果我正在讲述/修改数据,我应该通过索引硬编码索引访问文件的元素,即 targetFile.getElement(5);通过硬编码标识符(内部翻译成索引),即 target.getElem
在 Linux 上,我想知道要调用什么“C”API 来获取每个 CPU 的统计信息。 我知道并且可以从我的应用程序中读取 /proc/loadavg,但这是系统范围的负载平均值,而不是每个 CPU 的
在客户端浏览器中使用 fetch api,GET 或 POST 没有问题,但 fetch 和 DELETE 有问题。它似乎将 DELETE 请求方法更改为 OPTIONS。 大多数研究表明是一个cor
我是一名优秀的程序员,十分优秀!