向 DataSource 添加值时,带有 CollectionView 的 IBDesignable 崩溃
IBDesignable with CollectionView crashes when add value to DataSource
我正在开发一个小型 UIView
组件,该组件在 UICollectionView
中显示主题标签,出于某些原因,我需要通过 Interface Builder 使其成为 "editable"...因此,我做到了 IBDesignable
.
一切正常,除了在 prepareForInterfaceBuilder
中我试图将一个对象附加到 datasource
,因此当集成到情节提要中的某处时列表会显示一些内容。
到达第 self.hashtags.append(hashtag)
行时崩溃。如果我删除这一行,视图将在故事板上正确呈现,如果我再次放置它 ---> 崩溃...在我进行了所有调试之后,似乎 IB 无法访问此 属性 或看到它为零.
我无法调试 任何东西,Xcode 不允许我调试 Storyboard > Editor 中的选定视图(在 macOS Mojave 上会导致错误)。我的视图没有 .xib
,并且都需要 init
的
我还检查了 Console.app 中的日志,但什么也没有。这是 Storyboard 给出的主要错误消息:
Main.storyboard:错误:IB Designables:无法呈现和更新 PublishViewController 的自动布局状态 (tSg-9E-Vz3):代理抛出异常。
代码(重要的)
@IBDesignable
class HashtagView: UIView {
@IBOutlet weak var height: NSLayoutConstraint?
var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
return view
}()
open var hashtags: [HashTag] = []
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setup()
self.hashtags.append(HashTag(word: "it works")) < CRASH
self.collectionView.reloadData()
self.layoutSubviews()
}
}
设置函数()
func setup() {
self.backgroundColor = UIColor.clear
self.backgroundColor = UIColor.Custom.ligthGray
self.clipsToBounds = true
self.layer.cornerRadius = self.cornerRadius
let alignedFlowLayout = AlignedCollectionViewFlowLayout(horizontalAlignment: .left, verticalAlignment: .top)
alignedFlowLayout.minimumLineSpacing = 5.0
alignedFlowLayout.minimumInteritemSpacing = 7.0
alignedFlowLayout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
self.collectionView.collectionViewLayout = alignedFlowLayout
self.collectionView.translatesAutoresizingMaskIntoConstraints = false
self.collectionView.delegate = self
self.collectionView.dataSource = self
self.collectionView.backgroundColor = UIColor.clear
self.collectionView.isScrollEnabled = false
self.collectionView.register(UINib(nibName: "RemovableTagCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "RemovableTagCollectionViewCell")
self.addSubview(self.collectionView)
self.collectionView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
self.collectionView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
self.collectionView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
self.collectionView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
所以设置绝对是相关的。显然 IB 在尝试为您的 UICollectionView 加载您的单元格时崩溃了。它无法加载 Nib 文件。它与刚刚同时崩溃的追加没有任何关系。我复制了您的问题,然后用代码创建了一个单元格,一切正常。如果这有助于回答您的问题,请告诉我。所有必需的代码都在那里。
import UIKit
struct HashTag {
var word:String?
}
class HashCollectionViewCell: UICollectionViewCell {
lazy var wordLabel : UILabel = {
let lbl = UILabel(frame: self.bounds)
lbl.font = UIFont.systemFont(ofSize: 17)
lbl.textColor = .black
return lbl
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(wordLabel)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.addSubview(wordLabel)
}
func configureWithTag(tag:HashTag) {
wordLabel.text = tag.word
}
}
@IBDesignable
class HashTagView: UIView {
private var sizingLabel = UILabel(frame: .zero)
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let view = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
view.autoresizingMask = [.flexibleWidth,.flexibleHeight]
return view
}()
var hashtags: [HashTag] = [HashTag(word: "this works")]
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup(){
sizingLabel.font = UIFont.systemFont(ofSize: 17)
self.addSubview(collectionView)
collectionView.frame = self.bounds
collectionView.backgroundColor = self.backgroundColor
collectionView.register(HashCollectionViewCell.self, forCellWithReuseIdentifier: "hashCell")
self.addSubview(collectionView)
for x in 0..<10{
addHashTag(tag: "This is more \(x)")
}
collectionView.delegate = self
collectionView.dataSource = self
}
func addHashTag(tag:String){
let newHash = HashTag(word: tag)
self.hashtags.append(newHash)
}
override func layoutSubviews() {
super.layoutSubviews()
collectionView.frame = self.bounds
}
}
extension HashTagView: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return hashtags.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "hashCell", for: indexPath) as? HashCollectionViewCell{
let tag = self.hashtags[indexPath.item]
cell.configureWithTag(tag: tag)
return cell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let tag = self.hashtags[indexPath.item]
sizingLabel.text = tag.word
sizingLabel.sizeToFit()
return sizingLabel.frame.size
}
}
结果:
2) 您可以将 nib 加载到以编程方式创建的单元格中,它会起作用。 对于作为编程单元格的部分,示例看起来像这样。
在单元格内使用 nib 的带有视图扩展的单元格代码:
extension UIView {
func loadNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nibName = type(of: self).description().components(separatedBy: ".").last!
let nib = UINib(nibName: nibName, bundle: bundle)
return nib.instantiate(withOwner: self, options: nil).first as! UIView
}
}
class HashCollectionViewCell: UICollectionViewCell {
var hashTagNib : HashTagNibView?
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup(){
if let htn = HashTagNibView().loadNib() as? HashTagNibView{
hashTagNib = htn
hashTagNib?.frame = self.bounds
hashTagNib?.autoresizingMask = [.flexibleWidth,.flexibleHeight]
self.addSubview(htn)
}
}
func configureWithTag(tag:HashTag) {
if let htn = hashTagNib{
htn.hashTagButtonLabel.setTitle(tag.word, for: .normal)
}
}
笔尖设置如下所示:
这可能会给你更多的灵活性,具体取决于你在做什么,结果是相似的,除了在 nib 示例中我使用了 UIButton。
我正在开发一个小型 UIView
组件,该组件在 UICollectionView
中显示主题标签,出于某些原因,我需要通过 Interface Builder 使其成为 "editable"...因此,我做到了 IBDesignable
.
一切正常,除了在 prepareForInterfaceBuilder
中我试图将一个对象附加到 datasource
,因此当集成到情节提要中的某处时列表会显示一些内容。
到达第 self.hashtags.append(hashtag)
行时崩溃。如果我删除这一行,视图将在故事板上正确呈现,如果我再次放置它 ---> 崩溃...在我进行了所有调试之后,似乎 IB 无法访问此 属性 或看到它为零.
我无法调试 任何东西,Xcode 不允许我调试 Storyboard > Editor 中的选定视图(在 macOS Mojave 上会导致错误)。我的视图没有 .xib
,并且都需要 init
的
我还检查了 Console.app 中的日志,但什么也没有。这是 Storyboard 给出的主要错误消息:
Main.storyboard:错误:IB Designables:无法呈现和更新 PublishViewController 的自动布局状态 (tSg-9E-Vz3):代理抛出异常。
代码(重要的)
@IBDesignable
class HashtagView: UIView {
@IBOutlet weak var height: NSLayoutConstraint?
var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
return view
}()
open var hashtags: [HashTag] = []
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setup()
self.hashtags.append(HashTag(word: "it works")) < CRASH
self.collectionView.reloadData()
self.layoutSubviews()
}
}
设置函数()
func setup() {
self.backgroundColor = UIColor.clear
self.backgroundColor = UIColor.Custom.ligthGray
self.clipsToBounds = true
self.layer.cornerRadius = self.cornerRadius
let alignedFlowLayout = AlignedCollectionViewFlowLayout(horizontalAlignment: .left, verticalAlignment: .top)
alignedFlowLayout.minimumLineSpacing = 5.0
alignedFlowLayout.minimumInteritemSpacing = 7.0
alignedFlowLayout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
self.collectionView.collectionViewLayout = alignedFlowLayout
self.collectionView.translatesAutoresizingMaskIntoConstraints = false
self.collectionView.delegate = self
self.collectionView.dataSource = self
self.collectionView.backgroundColor = UIColor.clear
self.collectionView.isScrollEnabled = false
self.collectionView.register(UINib(nibName: "RemovableTagCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "RemovableTagCollectionViewCell")
self.addSubview(self.collectionView)
self.collectionView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
self.collectionView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
self.collectionView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
self.collectionView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
所以设置绝对是相关的。显然 IB 在尝试为您的 UICollectionView 加载您的单元格时崩溃了。它无法加载 Nib 文件。它与刚刚同时崩溃的追加没有任何关系。我复制了您的问题,然后用代码创建了一个单元格,一切正常。如果这有助于回答您的问题,请告诉我。所有必需的代码都在那里。
import UIKit
struct HashTag {
var word:String?
}
class HashCollectionViewCell: UICollectionViewCell {
lazy var wordLabel : UILabel = {
let lbl = UILabel(frame: self.bounds)
lbl.font = UIFont.systemFont(ofSize: 17)
lbl.textColor = .black
return lbl
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(wordLabel)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.addSubview(wordLabel)
}
func configureWithTag(tag:HashTag) {
wordLabel.text = tag.word
}
}
@IBDesignable
class HashTagView: UIView {
private var sizingLabel = UILabel(frame: .zero)
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let view = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
view.autoresizingMask = [.flexibleWidth,.flexibleHeight]
return view
}()
var hashtags: [HashTag] = [HashTag(word: "this works")]
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup(){
sizingLabel.font = UIFont.systemFont(ofSize: 17)
self.addSubview(collectionView)
collectionView.frame = self.bounds
collectionView.backgroundColor = self.backgroundColor
collectionView.register(HashCollectionViewCell.self, forCellWithReuseIdentifier: "hashCell")
self.addSubview(collectionView)
for x in 0..<10{
addHashTag(tag: "This is more \(x)")
}
collectionView.delegate = self
collectionView.dataSource = self
}
func addHashTag(tag:String){
let newHash = HashTag(word: tag)
self.hashtags.append(newHash)
}
override func layoutSubviews() {
super.layoutSubviews()
collectionView.frame = self.bounds
}
}
extension HashTagView: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return hashtags.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "hashCell", for: indexPath) as? HashCollectionViewCell{
let tag = self.hashtags[indexPath.item]
cell.configureWithTag(tag: tag)
return cell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let tag = self.hashtags[indexPath.item]
sizingLabel.text = tag.word
sizingLabel.sizeToFit()
return sizingLabel.frame.size
}
}
结果:
2) 您可以将 nib 加载到以编程方式创建的单元格中,它会起作用。 对于作为编程单元格的部分,示例看起来像这样。
在单元格内使用 nib 的带有视图扩展的单元格代码:
extension UIView {
func loadNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nibName = type(of: self).description().components(separatedBy: ".").last!
let nib = UINib(nibName: nibName, bundle: bundle)
return nib.instantiate(withOwner: self, options: nil).first as! UIView
}
}
class HashCollectionViewCell: UICollectionViewCell {
var hashTagNib : HashTagNibView?
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup(){
if let htn = HashTagNibView().loadNib() as? HashTagNibView{
hashTagNib = htn
hashTagNib?.frame = self.bounds
hashTagNib?.autoresizingMask = [.flexibleWidth,.flexibleHeight]
self.addSubview(htn)
}
}
func configureWithTag(tag:HashTag) {
if let htn = hashTagNib{
htn.hashTagButtonLabel.setTitle(tag.word, for: .normal)
}
}
笔尖设置如下所示:
这可能会给你更多的灵活性,具体取决于你在做什么,结果是相似的,除了在 nib 示例中我使用了 UIButton。