MSAutoView
在创建 iOS 应用时,您需要处理很多视图。随着项目的增长,管理不同视图将变得痛苦。有时,单个视图会被多个地方以小的变化使用。您觉得如果有一个地方可以管理所有视图会节省您很多麻烦。这正是 MSAutoView 所做的。
目录
安装
MSAutoView 通过 CocoaPods 提供。要安装它,只需将以下行添加到 Podfile:
pod 'MSAutoView'
准备条件
- XCode 9
结构
每个视图都有自己的xib文件和swift文件。xib文件将包含视图层次结构,而swift文件将保存此视图的逻辑。
MSAutoView
是UIView
的子类。在创建继承自MSAutoView
的类时,它将自动找到相应的xib并将其添加为子视图。它还会为子视图创建顶部、底部、左侧和右侧约束以将其固定。
注意:xib中的视图不应存在约束歧义,否则将无法正确显示。
用法
最小配置
Storyboard
import UIKit
import MSAutoView
class ListingView: MSAutoView {
}
注意:为了使最小配置正常工作,类的名称应与xib的名称相同
定制
以编程方式更新视图
当然,如果你的可重用视图无法通过编程方式传递数据,那它将毫无价值。为此,请按照以下步骤进行操作:
-
将 nib 的
File's Owner
类设置为之前创建的类 -
向类中添加输出口
class ListingView: MSAutoView {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var detailsLabel: UILabel!
@IBOutlet weak var priceLabel: UILabel!
}
-
在 nib 文件中,将输出口连接到相应的视图
-
在视图控制器中,为视图创建一个输出口
@IBOutlet weak var listingView: ListingView!
-
在故事板中将视图控制器的输出口连接到视图
-
更改视图控制器中标签的文字值
listingView.titleLabel.text = "This is a default title"
listingView.detailsLabel.text = "This is a default details"
listingView.priceLabel.text = "300"
向视图添加变量以更新视图
直接更新标签中的文字并不是一个好习惯。因此,你可以创建变量来保存值,当值改变时更新视图。下面是操作步骤:
- 在
ListingView
类文件中,添加以下变量
class ListingView: MSAutoView {
//Outlets
var title: String?
var details: String?
var price: String?
}
- 重写
updateView()
函数以设置标签文字
class ListingView: MSAutoView {
//Outlets
//Variables
override func updateView() {
super.updateView()
titleLabel.text = title
detailsLabel.text = details
priceLabel.text = price
}
}
- 在视图控制器中任一地方设置值,并更新视图
listingView.title = "This is a default title"
listingView.details = "This is a default details"
listingView.price = "300"
listingView.updateView()
使用可检查变量
您可以使用可检查变量来保存标签的值
class ListingView: MSAutoView {
//Outlets
@IBInspectable var title: String?
@IBInspectable var details: String?
@IBInspectable var price: Double = 0
//Functions
}
创建可检查变量后,您可以在 nib 或视图控制器中设置它们
从任一视图创建表视图单元格
如果您想要在第 UITableView
中避免为每个视图创建新的单元格类,您可以使用由代码库提供的通用类 MSTableViewCell<T>
。您可以使用它的方法如下:
- 创建一个表格视图
- 程序化注册单元格
tableView.register(MSTableViewCell<ListingView>.self, forCellWithReuseIdentifier: "Cell")
或者,MSAutoView
为 UIView
添加了一个扩展,该扩展包含返回任何视图的 table view cell 的变量。因此,您可以这样注册 cell:
tableView.register(ListingView.tableViewCell.self, forCellWithReuseIdentifier: "Cell")
- 在
tableView(_:cellForRowAt:)
中,按如下方式从重用标识符中预取 cell
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! MSTableViewCell<ListingView>
- 您可以使用 cell 上的变量
mainView
访问封装的视图
cell.mainView.doSomething()
此类是一个 open
类,因此您可以按要求创建子类以添加更多功能。
从任何视图创建 collection view cell
从任何视图创建 collection view cell 与创建 table view cell 类似。但,您会使用扩展变量 collectionViewCell
而不是 tableViewCell
获取任何视图的 table view cell 或 collection view cell(如果存在)
MSAutoView
现在有两个属性可以被设置为允许稍后从视图中检索 table view cell/collection view cell
public weak var tableViewCell: UITableViewCell?
public weak var collectionViewCell: UICollectionViewCell?
它与 superView
变量类似,只是当设置视图时设置 cell,然后在代理函数中通过调用 view.tableViewCell
或 view.collectionViewCell
获取对应的 cell。
从任何视图创建滚动视图
创建滚动视图与创建 table view/collection view 相同。假设您有一个名为 TallView
的长视图,该视图有一个名为 anyLabel
的标签,您可以在视图控制器中进行以下操作:
let tallView = TallView()
tallView.anyLabel.text = "This is a dummy text"
view.addSubviewWithConstraints(tallView.scrollView)
为视图的所有实例使用默认值
您可以通过以下两种方式完成此操作:
- 在代码中设置值
var title: String? = "Default Title"
- 如果是可检查的变量,则将在 xib 文件中设置其值
在特定视图控制器中设置视图的默认值
如果您的类变量是可检查的,则可以在故事板中更改其默认值
通过编程方式向主 xib 视图添加填充
总结:类将通过添加顶部、左、底和右约束来嵌套 xib 视图到主视图中。要向约束添加填充,可以将它们的常量值设置为除了 0 以外的任何值。您可以在 initView()
函数中这样做
override func initView() {
super.initView { (top, left, bottom, right) in
top.constant = 10
left.constant = 10
bottom.constant = -10
right.constant = -10
}
updateView()
}
请注意,底部和右边的常量应为负值以实现预期效果
或者您可以在之后添加填充
fileprivate var leftLayoutConstraint: NSLayoutConstraint?
fileprivate var rightLayoutConstraint: NSLayoutConstraint?
override func initView() {
super.initView {[weak self] (top, left, bottom, right) in
self?.leftLayoutConstraint = left
self?.rightLayoutConstraint = right
}
}
// update the margin whenever you want.
func updateMargin(_ left: CGFloat, _ right: CGFloat) {
self.leftLayoutConstraint?.constant = left
self.rightLayoutConstraint?.constant = right
}
使用与类名不同的名称的 xib
如果您希望将 xib 命名为不同于类名的名称,可以这样做
- 在类文件中,重写
initView()
函数
class ListingView: MSAutoView {
//Outlets
//Variables
override func initView() {
self.xibName = "ListingView2"
super.initView()
}
}
使用与类包不同的包的 xib
class ListingView: MSAutoView {
//Outlets
//Variables
override func initView() {
self.xibBundle = Bundle(identifier: "Identifier")
super.initView()
}
}
使用协议代替子类化
如果您从一个视图继承并且子类化不可行,可以使用该协议轻松嵌套视图
public protocol MSXibEmbedding: AnyObject {
var xibBundle: Bundle? { set get }
var xibName: String? { set get }
func loadXibMainView(constraintsConfiguration: ConstraintsConfiguration?)
func loadXibItems(xibItemsConfiguration: XibItemsConfiguration?)
}
协议函数有扩展函数,所以你不必担心实际的实现。只需让您的视图遵守 MSXibEmbedding
协议,在初始化视图时调用 loadXibMainView()
使用编程方式在另一个视图内部添加具有约束的视图
您可以通过将视图放置在彼此内部轻松聚合视图。您可以使用下面的 UIView
扩展函数这样做
public func addSubviewWithConstraints(_ subview: UIView, constraintsConfiguration: ConstraintsConfiguration? = nil)
示例
parentView.addSubviewWithConstraints(childView)
使用带有多个项目的 xib
您可能想使用一个具有多个顶级视图的 xib。也许还有其他非视图对象。为此,按照以下方式重写 initView()
override func initView() {
loadXibItems { (items) in
//Use xib items here, maybe save them in variables ...
}
}
注意:如果您多次调用 loadXibItems
,先前加载的 xib 项将被丢弃,新项将可用。因此,如果您尝试访问已丢弃的项,可能会得到 nil
作者
- 马赫桑蒂娜 - 初始工作
许可证
本项目采用 MIT 许可证 - 有关详细信息,请参阅 LICENSE.md 文件