heightForRowAtIndexPath间歇性崩溃 [英] heightForRowAtIndexPath crashing intermittently
问题描述
我有一个拥有约30名活跃用户和500多名注册用户的应用,这个问题只发生在9.2使用iPhone 6的人身上。
I have an app with about 30 active users and 500+ registered users and this issue is only happening with one person who is on 9.2 using an iPhone 6.
我可以从崩溃报告中看到她有超过60次崩溃,她说有时候问题还行,而不是其他问题。
I can see from crash reports she's had over 60 crashes and she has said that the problem is OK sometimes and not others.
我在这里有相同的测试设备,没有问题正在发生。
I have the same test device here and no issue is happening.
我无法从结构中获取大量崩溃报告详细信息,但崩溃发生在以下方法中且应用程序崩溃在这个方法的最终,我可以从她对问题的描述中看出:
I can't get much out of the crash report details from fabric but the crash is happening at the following method and the app is crashing at the final else of this method, I can tell from her description of the problem:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
let bounds = UIScreen.mainScreen().bounds
var screenWidth = bounds.size.width
let screenHeight = bounds.size.height
if indexPath.row == 0 {
let font = UIFont(name: "Helvetica Neue", size: 17.0)
let heightCalc = heightForView(self.postDescription!, font: font!, width: screenWidth - 32)
if self.photoWidth != nil{
let imageAspectRatio = self.photoWidth!/self.photoHeight!
var imageViewFrameHeight = screenWidth/imageAspectRatio
if self.portBool {
if imageViewFrameHeight > (screenHeight - 64) {
screenWidth = screenWidth * 0.60
imageViewFrameHeight = imageViewFrameHeight * 0.60
}
}
return imageViewFrameHeight + 136 + heightCalc + 26
//return 557
}
else{
return 136 + heightCalc + 30
}
}
else if indexPath.row == 1 {
return 50.0
}
else if indexPath.row == 2{
return 40.0
}
else{
if self.commentsDetailed != nil && self.commentsDetailed!.count >= (indexPath.row - 3)
{
let commentsDetailed = self.commentsDetailed![indexPath.row-3]
let font = UIFont(name: "Helvetica Neue", size: 14.0)
let heightCalc = heightForView(commentsDetailed.comment!, font: font!, width: screenWidth - 51)
if commentsDetailed.authorId == Prefs.userId.description {
return 45 + heightCalc + 40 + 30
//return 131.5
}
else{
return 45 + heightCalc + 40
//return 101.5
}
}
else {
return 80.0
}
}
}
对于那些想知道的人,我需要计算高度以避免在发生时发生的抖动滚动我正在使用表vi自动尺寸。所以我只需要在这里解决问题而不是切换方法。
For those wondering, I need to calculate the height to avoid a jittery scroll which was happening when I was using the table view automatic dimension. So I just need to solve the issue within here and not switch approach.
来自crashlytics的一些信息:
Some info from crashlytics:
EXC_BREAKPOINT
Thread : Crashed: Thread
0 ProjectName 0x10008a64c specialized NewFeedDetailedController.tableView(UITableView, heightForRowAtIndexPath : NSIndexPath) -> CGFloat (NewFeedDetailedController.swift)
1 ProjectName 0x100085258 @objc NewFeedDetailedController.tableView(UITableView, heightForRowAtIndexPath : NSIndexPath) -> CGFloat (NewFeedDetailedController.swift)
2 UIKit 0x187683638 __66-[UISectionRowData refreshWithSection:tableView:tableViewRowData:]_block_invoke + 396
3 UIKit 0x187641818 -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 3948
4 UIKit 0x1876407d4 -[UITableViewRowData rectForFooterInSection:heightCanBeGuessed:] + 412
5 UIKit 0x187640590 -[UITableViewRowData heightForTable] + 64
6 UIKit 0x18764039c -[UITableView _updateContentSize] + 220
7 UIKit 0x1878a6f60 -[UITableView _rebuildGeometry] + 44
8 UIKit 0x1876462c8 -[UITableView didMoveToWindow] + 144
9 UIKit 0x18755705c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1496
10 UIKit 0x18757c568 -[UIScrollView _didMoveFromWindow:toWindow:] + 92
11 UIKit 0x187556d7c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 760
12 UIKit 0x187556310 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 152
13 Foundation 0x183189500 -[NSISEngine withBehaviors:performModifications:] + 168
14 UIKit 0x187556194 -[UIView(Hierarchy) _postMovedFromSuperview:] + 532
15 UIKit 0x187563b80 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1784
16 UIKit 0x187755600 -[_UIParallaxDimmingView didMoveToWindow] + 180
17 UIKit 0x18755705c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1496
18 UIKit 0x187556d7c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 760
19 UIKit 0x187556310 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 152
20 Foundation 0x183189500 -[NSISEngine withBehaviors:performModifications:] + 168
21 UIKit 0x187556194 -[UIView(Hierarchy) _postMovedFromSuperview:] + 532
22 UIKit 0x187563b80 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1784
23 UIKit 0x1877f5db4 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke_2 + 1656
24 UIKit 0x18756a964 +[UIView(Animation) performWithoutAnimation:] + 80
25 UIKit 0x187755118 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke + 260
26 UIKit 0x187870840 +[UIView(Internal) _performBlockDelayingTriggeringResponderEvents:] + 220
27 UIKit 0x187754c90 -[_UINavigationParallaxTransition animateTransition:] + 1060
28 UIKit 0x18770e6a0 -[UINavigationController _startCustomTransition:] + 3544
29 UIKit 0x18761a9b8 -[UINavigationController _startDeferredTransitionIfNeeded:] + 688
30 UIKit 0x18761a694 -[UINavigationController __viewWillLayoutSubviews] + 60
31 UIKit 0x18761a5fc -[UILayoutContainerView layoutSubviews] + 208
32 UIKit 0x187557778 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 656
33 QuartzCore 0x184f66b2c -[CALayer layoutSublayers] + 148
34 QuartzCore 0x184f61738 CA::Layer::layout_if_needed(CA::Transaction*) + 292
35 QuartzCore 0x184f615f8 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 32
36 QuartzCore 0x184f60c94 CA::Context::commit_transaction(CA::Transaction*) + 252
37 QuartzCore 0x184f609dc CA::Transaction::commit() + 512
38 UIKit 0x18754dc78 _afterCACommitHandler + 180
39 CoreFoundation 0x182820588 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
40 CoreFoundation 0x18281e32c __CFRunLoopDoObservers + 372
41 CoreFoundation 0x18281e75c __CFRunLoopRun + 928
42 CoreFoundation 0x18274d680 CFRunLoopRunSpecific + 384
43 GraphicsServices 0x183c5c088 GSEventRunModal + 180
44 UIKit 0x1875c4d90 UIApplicationMain + 204
45 ProjectName 0x1001663b0 main (AppDelegate.swift:21)
46 libdyld.dylib 0x1822ee8b8 start + 4
并且heightForView func:
And the heightForView func:
func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
label.font = font
label.text = text
label.sizeToFit()
return label.frame.height
}
更新了代码并检查了nil,但仍然为用户崩溃:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
let bounds = UIScreen.mainScreen().bounds
var screenWidth = bounds.size.width
let screenHeight = bounds.size.height
if indexPath.row == 0 {
CLSLogv("crashing in indexPath.Row = 0 %@", getVaList(["returning 50.0 here"]))
let font = UIFont(name: "Helvetica Neue", size: 17.0)
if let description = self.postDescription {
let heightCalc = heightForView(description, font: font!, width: screenWidth - 32)
if self.photoWidth != nil && self.photoHeight != nil {
CLSLogv("crashing in indexPath.Row = 0 %@", getVaList(["inside photowidth is not nil"]))
let imageAspectRatio = self.photoWidth!/self.photoHeight!
var imageViewFrameHeight = screenWidth/imageAspectRatio
if self.portBool {
if imageViewFrameHeight > (screenHeight - 64) {
screenWidth = screenWidth * 0.60
imageViewFrameHeight = imageViewFrameHeight * 0.60
}
}
return imageViewFrameHeight + 136.0 + heightCalc + 26.0
//return 557
}
else{
CLSLogv("crashing in indexPath.Row = 0 %@", getVaList(["when photowidth is nil"]))
return 136.0 + heightCalc + 30.0
}
}
else{
CLSLogv("crashing in indexPath.Row = 0 %@", getVaList(["unable to unwrap self.postDescription"]))
if self.photoWidth != nil && self.photoHeight != nil {
let imageAspectRatio = self.photoWidth!/self.photoHeight!
var imageViewFrameHeight = screenWidth/imageAspectRatio
if self.portBool {
if imageViewFrameHeight > (screenHeight - 64) {
screenWidth = screenWidth * 0.60
imageViewFrameHeight = imageViewFrameHeight * 0.60
}
}
return imageViewFrameHeight + 136.0 + 26.0
}
else{
return 136.0 + 30.0
}
}
}
else if indexPath.row == 1 {
CLSLogv("crashing in indexPath.Row = 1 %@", getVaList(["returning 50.0 here"]))
return 50.0
}
else if indexPath.row == 2 {
CLSLogv("crashing in indexPath.Row = 2 %@", getVaList(["returning 40.0 here"]))
return 40.0
}
else{
if self.commentsDetailed != nil && self.commentsDetailed!.count > (indexPath.row - 3)
{
if let commentsDetailed = self.commentsDetailed?[indexPath.row-3]{
let font = UIFont(name: "Helvetica Neue", size: 14.0)
if let comment = commentsDetailed.comment{
let heightCalc = heightForView(comment, font: font!, width: screenWidth - 51)
if commentsDetailed.authorId == Prefs.userId.description {
return 45.0 + heightCalc + 40.0 + 30.0
}
else{
return 45.0 + heightCalc + 40.0
}
}
else{
if commentsDetailed.authorId == Prefs.userId.description {
return 45.0 + 40.0 + 30.0
}
else{
return 45.0 + 40.0
}
}
}
else {
CLSLogv("in the else for defining commentsDetailed %a",getVaList(["commentsdetailed"]))
return 80.0
}
}
else {
CLSLogv("in the condition for checking commentsDetailed = nil - true %a", getVaList(["CRASH RELATED TO RETURNING 80 IF ARRAY IS NIL?"]))
return 80.0
}
}
}
推荐答案
如上所述错误是在最后一次关闭时反弹的数组:
The error is array out of bounce at the last else closure like you said:
if self.commentsDetailed != nil && self.commentsDetailed!.count >= (indexPath.row - 3)
{
let commentsDetailed = self.commentsDetailed![indexPath.row-3]
例如,如果数组大小为1,那么您可以索引的最后一个元素是arr [0]但是count> =(indexPath.row - 3)会让索引arr [1]导致错误。
If for example the array is size 1, then the last element you can index is arr[0] but count >= (indexPath.row - 3) will let indexing arr[1] which will cause the error.
由于重复调用此方法,因此还可以执行其他修改以进行优化。 (我建议可能在外面使用字体和其他变量,这样每次都不会创建它们。可能会有这样的优化,但我不确定)。
There are also other fixes you can do to optimize since this method is called repeatedly. (I'd suggest maybe having the fonts and other variables outside so that it doesn't create them each time. There maybe such optimization behind but I'm not sure).
我不得不重新编写整个游乐场才能找到问题,所以我想我只是在这里粘贴代码:)
I had to re-write the whole thing playground to find the problem so I guess I'll just paste the code here :)
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath:
NSIndexPath) -> CGFloat {
var screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
switch indexPath.row {
case 0:
guard let font = UIFont(name: "Helvetica Neue", size: 17.0) else {
print("Font not Found !")
break
}
let heightCalc = heightForView(self.postDescription! ?? "", font: font, width: screenWidth - 32)
guard let photoWidth = self.photoWidth, let photoHeight = self.photoHeight else {
return 136 + heightCalc + 30
}
let imageAspectRatio = photoWidth / photoHeight
var imageViewFrameHeight = screenWidth / imageAspectRatio
if self.portBool {
if imageViewFrameHeight > (screenHeight - 64) {
screenWidth = screenWidth * 0.60
imageViewFrameHeight = imageViewFrameHeight * 0.60
}
}
return imageViewFrameHeight + 136 + heightCalc + 26
//return 557
case 1: return 50.0
case 2: return 40.0
case _ where self.commentsDetailed != nil && indexPath.row >= 3:
let index = indexPath.row - 3
//I think your problem was here (your index can not be equal to the count!)
guard let detailed = self.commentsDetailed where detailed.count > index
else { break }
let commentsDetailed = detailed[index]
guard let font = UIFont(name: "Helvetica Neue", size: 14.0) else {
break //font not found
}
let heightCalc = heightForView(commentsDetailed.comment! ?? "", font: font, width: screenWidth - 51)
if commentsDetailed.authorId == Prefs.userId.description { //make sure author id is always string. sounds like a number
return 45 + heightCalc + 40 + 30
//return 131.5
}
else{
return 45 + heightCalc + 40
//return 101.5
}
default: return 80.0
}
}
这篇关于heightForRowAtIndexPath间歇性崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!