是否可以将 IBDesignable 与 UICollectionViewCells 一起使用并在情节提要中实时渲染它们?
Is it possible to use IBDesignable with UICollectionViewCells and live render them in storyboard?
我知道如何将@IBDesignable 与自定义视图一起使用。
但是是否可以对单元格使用 IBDesignable 并在故事板中渲染它们?
例如:我在故事板中有一个 collectionViewController,并添加了一个 uiCollectionCell 并指定 class 作为我的 customCellClass。
p.s:我知道在 collecionViews 和 tableViews 中使用 Xibs 我们必须在代码中调用方法 registerNib:forReuseIdentifer(我正在这样做)。只是想知道,是否可以在情节提要中看到它的渲染视图。
p.s2:我发现 this 并且它与 UIViews 完美配合,但不知道如何使其与 CollectionCells 和 TableCells 配合使用。 :(
经过大量测试和使用库后,我想到了这个:
您不应在 .nib
文件中添加 TableViewCell
或 CollectionViewCells
,而必须添加简单的视图。我不确定它是否会出现在情节提要中(尚未检查),但它会消除错误。现在您甚至可以使用 autoLayout
来调整单元格的大小。
是的。这是我在 Xcode 10.1 和 iOS 12 中发现的。将 @IBDesignable
添加到 UICollectionViewCell
的自定义子类确实间歇性地工作,但这更可靠:
- 将
@IBDesignable
添加到 UIView
的自定义子类
- 覆盖
layoutSubviews()
,并在那里定义外观
- 可选,如果您只想为 IB 定义虚拟数据,请覆盖
prepareForInterfaceBuilder()
- 在 Interface Builder
中将自定义视图添加到您的原型 UICollectionViewCell
- 您应该查看 Interface Builder "build" 视图并在您的客户视图中绘制您的更改(我发现这也不可靠。如果没有任何反应并且
Menu / Editor / Automatically Refresh Views
被选中,请在界面生成器)
例子Class
@IBDesignable
class Avatar: UIView {
// Despite not being used for views designed in Interface Builder, must still be defined for custom UIView subclasses with @IBDesignable, or IB will report errors
override init(frame: CGRect) {
super.init(frame: frame)
}
// Used when a view is designed inside a view controller scene in Interface Builder and assigned to this custom UIView subclass
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.width / 2
self.backgroundColor = UIColor.gray
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.backgroundColor = UIColor.blue
}
}
是的。这是我的做法。
首先确保 NIB 文件的文件所有者设置为您的自定义单元格 class。检查 this
覆盖 prepareForInterfaceBuilder
方法并在原型单元格的 contentView
中添加来自 NIB 文件的 contentView
。这是它的样子。
// ArticleTableViewCell.swift
import UIKit
@IBDesignable
class ArticleTableViewCell: UITableViewCell {
@IBOutlet weak var authorLabel: UILabel!
@IBOutlet weak var authorImage: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var dateCreatedLabel: UILabel!
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
addNIBContentView(toView: contentView)
}
private func addNIBContentView() {
let view = loadContentViewFromNib()
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
contentView.addSubview(view)
}
private func loadContentViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
// Make sure your NIB file is named the same as this class, or else
// Put the name of NIB file manually (without the file extension)
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
}
- 现在将 table 视图中原型单元格的自定义 class 设置为上面的那个并刷新视图。
Editor > Refresh All Views
如果还是没有出现。只需清除构建文件夹并再次刷新所有视图。
Product > Clean Build Folder
我为自己做了一个方便的扩展,以重用所有 UITableView
s/UICollectionView
s
中的最后两个函数
// ViewExtensions.swift
import UIKit
extension UIView {
func addNIBContentView(toView contentView: UIView? = nil) {
let view = loadContentViewFromNib()
// Use bounds not frame or it'll be offset
view.frame = bounds
// Make the view stretch with containing view
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
if let contentView = contentView {
contentView.addSubview(view)
} else {
addSubview(view)
}
}
private func loadContentViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
// Make sure your NIB file is named the same as it's class
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
}
// ArticleTableViewCell.swift
import UIKit
@IBDesignable
class ArticleTableViewCell: UITableViewCell {
@IBOutlet weak var authorLabel: UILabel!
@IBOutlet weak var authorImage: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var dateCreatedLabel: UILabel!
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
addNIBContentView(toView: contentView)
}
}
我知道如何将@IBDesignable 与自定义视图一起使用。 但是是否可以对单元格使用 IBDesignable 并在故事板中渲染它们?
例如:我在故事板中有一个 collectionViewController,并添加了一个 uiCollectionCell 并指定 class 作为我的 customCellClass。
p.s:我知道在 collecionViews 和 tableViews 中使用 Xibs 我们必须在代码中调用方法 registerNib:forReuseIdentifer(我正在这样做)。只是想知道,是否可以在情节提要中看到它的渲染视图。
p.s2:我发现 this 并且它与 UIViews 完美配合,但不知道如何使其与 CollectionCells 和 TableCells 配合使用。 :(
经过大量测试和使用库后,我想到了这个:
您不应在 .nib
文件中添加 TableViewCell
或 CollectionViewCells
,而必须添加简单的视图。我不确定它是否会出现在情节提要中(尚未检查),但它会消除错误。现在您甚至可以使用 autoLayout
来调整单元格的大小。
是的。这是我在 Xcode 10.1 和 iOS 12 中发现的。将 @IBDesignable
添加到 UICollectionViewCell
的自定义子类确实间歇性地工作,但这更可靠:
- 将
@IBDesignable
添加到UIView
的自定义子类
- 覆盖
layoutSubviews()
,并在那里定义外观 - 可选,如果您只想为 IB 定义虚拟数据,请覆盖
prepareForInterfaceBuilder()
- 在 Interface Builder 中将自定义视图添加到您的原型
- 您应该查看 Interface Builder "build" 视图并在您的客户视图中绘制您的更改(我发现这也不可靠。如果没有任何反应并且
Menu / Editor / Automatically Refresh Views
被选中,请在界面生成器)
UICollectionViewCell
例子Class
@IBDesignable
class Avatar: UIView {
// Despite not being used for views designed in Interface Builder, must still be defined for custom UIView subclasses with @IBDesignable, or IB will report errors
override init(frame: CGRect) {
super.init(frame: frame)
}
// Used when a view is designed inside a view controller scene in Interface Builder and assigned to this custom UIView subclass
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.width / 2
self.backgroundColor = UIColor.gray
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.backgroundColor = UIColor.blue
}
}
是的。这是我的做法。
首先确保 NIB 文件的文件所有者设置为您的自定义单元格 class。检查 this
覆盖
prepareForInterfaceBuilder
方法并在原型单元格的contentView
中添加来自 NIB 文件的contentView
。这是它的样子。
// ArticleTableViewCell.swift
import UIKit
@IBDesignable
class ArticleTableViewCell: UITableViewCell {
@IBOutlet weak var authorLabel: UILabel!
@IBOutlet weak var authorImage: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var dateCreatedLabel: UILabel!
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
addNIBContentView(toView: contentView)
}
private func addNIBContentView() {
let view = loadContentViewFromNib()
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
contentView.addSubview(view)
}
private func loadContentViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
// Make sure your NIB file is named the same as this class, or else
// Put the name of NIB file manually (without the file extension)
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
}
- 现在将 table 视图中原型单元格的自定义 class 设置为上面的那个并刷新视图。
Editor > Refresh All Views
如果还是没有出现。只需清除构建文件夹并再次刷新所有视图。
Product > Clean Build Folder
我为自己做了一个方便的扩展,以重用所有 UITableView
s/UICollectionView
s
// ViewExtensions.swift
import UIKit
extension UIView {
func addNIBContentView(toView contentView: UIView? = nil) {
let view = loadContentViewFromNib()
// Use bounds not frame or it'll be offset
view.frame = bounds
// Make the view stretch with containing view
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
if let contentView = contentView {
contentView.addSubview(view)
} else {
addSubview(view)
}
}
private func loadContentViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
// Make sure your NIB file is named the same as it's class
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
}
// ArticleTableViewCell.swift
import UIKit
@IBDesignable
class ArticleTableViewCell: UITableViewCell {
@IBOutlet weak var authorLabel: UILabel!
@IBOutlet weak var authorImage: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var dateCreatedLabel: UILabel!
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
addNIBContentView(toView: contentView)
}
}