Ios 为什么总是初始化19个单元格?
我正在学习Swift中的TableView。我的老师问我这个问题:“你有20个单元格,但是屏幕上显示了3个单元格。有多少个单元格已经初始化,为什么 这是我的代码。我尝试了20多个单元格,总是初始化了19个单元格。有人能给我解释一下为什么吗?非常感谢 我在iPhone11Promax和iOS13.1上进行了测试Ios 为什么总是初始化19个单元格?,ios,swift,uitableview,cell,Ios,Swift,Uitableview,Cell,我正在学习Swift中的TableView。我的老师问我这个问题:“你有20个单元格,但是屏幕上显示了3个单元格。有多少个单元格已经初始化,为什么 这是我的代码。我尝试了20多个单元格,总是初始化了19个单元格。有人能给我解释一下为什么吗?非常感谢 我在iPhone11Promax和iOS13.1上进行了测试 override func viewDidLoad() { super.viewDidLoad() myTable.register(UINib(nibNa
override func viewDidLoad() {
super.viewDidLoad()
myTable.register(UINib(nibName: "ContactCell", bundle: nil), forCellReuseIdentifier: "ContactCell")
myTable.dataSource = self
myTable.delegate = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ContactCell", for: indexPath) as! ContactCell
cell.textLabel?.text = "Superhero"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return myTable.frame.size.height / 3.0
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.section)
print(indexPath.row)
}
将此代码保存在另一个文件中
class ContactCell: UITableViewCell {
@IBOutlet weak var cellShow: UIView!
override func awakeFromNib() {
super.awakeFromNib()
print("awakeFromNib")
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
来自苹果的文档():
在项目出现在屏幕上之前,表视图会为表可见部分中的项目调用此方法。当用户滚动时,表视图只会在项目在屏幕上移动时调用该方法。无论项目以前是否出现在屏幕上,它都会在每次项目出现在屏幕上时调用该方法
布局期间,表视图将开始填充。在此过程中,将确定元素的大小。根据单元格的初始高度和表视图的高度,可以先为可能出现的行调用heightForRowAt
,然后为可能出现的行调用,然后为将出现的行调用(以及可能刚刚脱离屏幕的行)
将print()
语句添加到heightForRowAt
func中,如下所示:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// add this line
print(indexPath)
return myTable.frame.size.height / 3.0
}
在我的快速测试中,如果根据我的表视图的高度适合7个默认高度行,我会在调试输出中看到:
[0, 0]
[0, 0]
[0, 0]
[0, 1]
[0, 1]
[0, 1]
[0, 2]
[0, 2]
[0, 2]
[0, 3]
[0, 3]
[0, 3]
[0, 4]
[0, 4]
[0, 4]
[0, 5]
[0, 5]
[0, 5]
[0, 6]
[0, 6]
[0, 6]
如您所见,7个单元格正在初始化,每个单元格调用heightForRowAt
三次
编辑:ugh…从零开始…将错误的6更改为正确的7
附加说明 如果设置
.estimateDroweight
,例如:
myTable.estimatedRowHeight = 150
您将看到越来越少的单元格被初始化,并且具有:
myTable.estimatedRowHeight = 10
您将看到更多单元格被初始化,因为自动布局将使用该值作为初始行高,而不是默认行高
另外,如果您想进一步了解单元格的重用方式,请将其添加到didSelectRowAt
处理程序中(这只是调试/开发功能,可能对生产代码没有用处):
在我的情况下(不设置.estimateDroweight
),我得到:
致:
现在,当选择一行并打印出“reusableCells”时,您可以看到哪些单元格实际位于“池”中。我的结果更改为:
Optional({
ContactCell = (
"<MyTest.ContactCell: 0x7fef77608330; baseClass = UITableViewCell; frame = (0 300; 295 100); text = 'Superhero 3'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d36d20>>",
"<MyTest.ContactCell: 0x7fef776091b0; baseClass = UITableViewCell; frame = (0 400; 295 100); text = 'Superhero 4'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37120>>",
"<MyTest.ContactCell: 0x7fef7760a030; baseClass = UITableViewCell; frame = (0 500; 295 100); text = 'Superhero 5'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37500>>",
"<MyTest.ContactCell: 0x7fef7760aeb0; baseClass = UITableViewCell; frame = (0 600; 295 100); text = 'Superhero 6'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37920>>"
);
})
可选({
ContactCell=(
"",
"",
"",
""
);
})
向我显示第4、5、6和7行的单元格(如
text=
属性中所示——同样是基于零的)已初始化并位于“重用池”中".您如何知道它正在初始化19个单元格,请告诉我您在哪里看到它在这样做。我这样问是因为您不知道它正在这样做,除非您有另一个函数正在解析表视图中的可见单元格或遍历视图树以在调试器中手动控制它们。您如何知道它是19个?因为只有单元格是b正在初始化,使其适合您的屏幕。证明:尝试旋转您的设备–它将更少(假设您从纵向转到横向)。您可以在func awakeFormNib中看到。当单元格初始化时,我打印“awakefromNib”。然后我计数。如果我重新运行100个单元格,则始终打印19行“awakefromNib”@Kevin.D这不是它的工作原理,这与内存中存储了多少个单元无关。我认为LinusGeffarth是对的。我试过iphone 8是15个单元,iphone 11 pro是17个单元谢谢。这确实很有帮助,但是cellForRowAt
为iphone 11打印了18个单元。我只能假设,在自动布局引擎启动之前“在表视图中”假定单元格的默认高度(44pt),这将导致812/44=18个完整单元格。@Desdnova-有关说明和其他信息,请参阅我的编辑。
Optional({
ContactCell = (
"<MyTest.ContactCell: 0x7fd0ccc295b0; baseClass = UITableViewCell; frame = (0 300; 295 100); text = 'Superhero'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x6000010fecc0>>",
"<MyTest.ContactCell: 0x7fd0ccc2a2a0; baseClass = UITableViewCell; frame = (0 400; 295 100); text = 'Superhero'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x6000010ff0c0>>",
"<MyTest.ContactCell: 0x7fd0ccc2ad90; baseClass = UITableViewCell; frame = (0 500; 295 100); text = 'Superhero'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x6000010ff4a0>>",
"<MyTest.ContactCell: 0x7fd0ccc2ba80; baseClass = UITableViewCell; frame = (0 600; 295 100); text = 'Superhero'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x6000010ff8a0>>"
);
})
cell.textLabel?.text = "Superhero"
cell.textLabel?.text = "Superhero \(indexPath.row)"
Optional({
ContactCell = (
"<MyTest.ContactCell: 0x7fef77608330; baseClass = UITableViewCell; frame = (0 300; 295 100); text = 'Superhero 3'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d36d20>>",
"<MyTest.ContactCell: 0x7fef776091b0; baseClass = UITableViewCell; frame = (0 400; 295 100); text = 'Superhero 4'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37120>>",
"<MyTest.ContactCell: 0x7fef7760a030; baseClass = UITableViewCell; frame = (0 500; 295 100); text = 'Superhero 5'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37500>>",
"<MyTest.ContactCell: 0x7fef7760aeb0; baseClass = UITableViewCell; frame = (0 600; 295 100); text = 'Superhero 6'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37920>>"
);
})