之前调试期间,一直不知道为何程序会挂掉:
2016-01-14 17:24:25.876 JianDao[36035:1663772] *** Terminating app due to uncaught exception ‘NSRangeException’, reason: ‘*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray’ *** First throw call stack: ( 0 CoreFoundation 0x013f8a14 __exceptionPreprocess + 180 1 libobjc.A.dylib 0x036e9e02 objc_exception_throw + 50 2 CoreFoundation 0x0139ed70 __CFArrayGetTypeID_block_invoke + 0 3 libswiftCore.dylib 0x03ae8cd4 _TFVSs12_ArrayBuffer19_getElementSlowPathurfGS_q__FSiPSs9AnyObject_ + 388 4 libswiftCore.dylib 0x03ae7a4c _TFVSs12_ArrayBuffer10getElementurfGS_q__FTSi32hoistedIsNativeNoTypeCheckBufferSb_q_ + 140 5 libswiftCore.dylib 0x03aff675 _TFSag9subscriptFSiq_ + 149 6 JianDao 0x001e102b _TFC7JianDao26ConversationViewController37updateConversationCellFromCellAndItemfS0_FTCS_25ConversationTableViewCell19curConversationItemCS_16ConversationItem_T_ + 3163 7 JianDao 0x001dee98 _TFC7JianDao26ConversationViewController9tableViewfS0_FTCSo11UITableView21cellForRowAtIndexPathCSo11NSIndexPath_CSo15UITableViewCell + 312 8 JianDao 0x001def49 _TToFC7JianDao26ConversationViewController9tableViewfS0_FTCSo11UITableView21cellForRowAtIndexPathCSo11NSIndexPath_CSo15UITableViewCell + 89 9 UIKit 0x023a1398 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 822 10 UIKit 0x023a14e1 -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 90 11 UIKit 0x02371948 -[UITableView _updateVisibleCellsNow:isRecursive:] + 3347 12 UIKit 0x023900d6 __29-[UITableView layoutSubviews]_block_invoke + 52 13 UIKit 0x023ab19e -[UITableView _performWithCachedTraitCollection:] + 88 14 UIKit 0x0238ffab -[UITableView layoutSubviews] + 214 15 UIKit 0x022e6008 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 810 16 libobjc.A.dylib 0x036fe059 -[NSObject performSelector:withObject:] + 70 17 QuartzCore 0x0202c80a -[CALayer layoutSublayers] + 144 18 QuartzCore 0x020204ee _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 388 19 QuartzCore 0x02020352 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26 20 QuartzCore 0x02012e8b _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 317 21 QuartzCore 0x02046e03 _ZN2CA11Transaction6commitEv + 561 22 QuartzCore 0x020476c4 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92 23 CoreFoundation 0x01311ffe __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30 24 CoreFoundation 0x01311f5e __CFRunLoopDoObservers + 398 25 CoreFoundation 0x013078dc __CFRunLoopRun + 1340 26 CoreFoundation 0x013070e6 CFRunLoopRunSpecific + 470 27 CoreFoundation 0x01306efb CFRunLoopRunInMode + 123 28 GraphicsServices 0x05090664 GSEventRunModal + 192 29 GraphicsServices 0x050904a1 GSEventRun + 104 30 UIKit 0x02219bfa UIApplicationMain + 160 31 JianDao 0x000bd87c main + 140 32 libdyld.dylib 0x0443ba21 start + 1 ) [libc++abi.dylib: terminating with uncaught exception of type NSException |
调试期间,只发现了:
此处有两个线程在运行,
难道是同时操作同一个变量导致的冲突?好像不像。
然后此处的错误:
index 0 beyond bounds for empty NSArray
其实很明显:
就是访问了一个数组,空的,但是使用了索引0,所以肯定会报错。
但是问题在于:
此处,不知道哪行代码导致此错误的。
然后通过:
_TFC7JianDao26ConversationViewController37updateConversationCellFromCellAndItemfS0_FTCS_25ConversationTableViewCell19curConversationItemCS_16ConversationItem_T_
可以得到是:
此处的函数:
updateConversationCellFromCellAndItem
中发生的问题
-》但是问题在于:
看了半天代码:
func updateConversationCellFromCellAndItem(cell:ConversationTableViewCell, curConversationItem:ConversationItem){ print("updateConversationCellFromCellAndItem") //1. title //cell.textLabel?.text = generateDisplayName(curConversationItem.msgTVC.contactItem) cell.textLabel?.text = curConversationItem.title //2. detail description cell.atMeStr = curConversationItem.descAtMeStr cell.detailStr = curConversationItem.descDetailStr if cell.atMeStr.isEmpty { cell.detailTextLabel?.text = cell.detailStr }else{ //add text but clear color for auto calculate detailTextLabel the frame size cell.detailTextLabel?.text = cell.atMeStr + cell.detailStr cell.detailTextLabel?.textColor = UIColor.clearColor() } //3. update time if let updateTimeView = cell.accessoryView?.subviews[0] { let updateTimeLabel = updateTimeView as! UILabel updateTimeLabel.text = curConversationItem.updateTimeStr } //4. header image and badge and red point let cornerHeaderImageView:UIImageView //remove previous if exist if let prevHeaderImageView = cell.imageView?.subviews[0] { prevHeaderImageView.removeFromSuperview() } //add new // cornerHeaderImageView = UIImageView(image: curConversationItem.msgTVC.contactItem.headerImageLarge) cornerHeaderImageView = UIImageView(image: curConversationItem.headerImage) if curConversationItem.badgeValue > 0 { var badgeValueStr = String(curConversationItem.badgeValue) if curConversationItem.badgeValue > 99 { badgeValueStr = "···" } let badgeView = drawRedBadgeView(badgeValueStr) badgeView.frame.origin.x = cornerHeaderImageView.frame.size.width – badgeView.frame.width + 4 badgeView.frame.origin.y -= 4 cornerHeaderImageView.addSubview(badgeView) } cell.imageView?.image = cornerHeaderImageView.image cell.imageView?.addSubview(cornerHeaderImageView) //TODO: add show red point } |
根本没有发现:
到底哪里有数组访问了??
最后的最后,找到根本原因了:
是:
//remove previous if exist if let prevHeaderImageView = cell.imageView?.subviews[0] { prevHeaderImageView.removeFromSuperview() } |
导致出错的:
此处的
if let prevHeaderImageView = cell.imageView?.subviews[0] |
在第一次调用此函数时,cell.imageView?.subviews
是空的,即empty的
所以
cell.imageView?.subviews[0]
的话,就导致出错了。
而之所以没有注意到这个错误:
主要是:
以为有了if去判断了,所以以为:
cell.imageView?.subviews[0]
肯定是有值的,而实际上是:
cell.imageView?.subviews
是有的值-》但是是empty的
此时
cell.imageView?.subviews[0]
就会出错。。。
其次是:
而对应的,上面也有类似的代码:
if let updateTimeView = cell.accessoryView?.subviews[0] { let updateTimeLabel = updateTimeView as! UILabel updateTimeLabel.text = curConversationItem.updateTimeStr } |
之所以没有问题
(其是因为:
调用此函数之前,已经有了:
let accessoryViewFrame = CGRectMake( 0, 0, updateTimeStrWidth,//HeightTableCellConversation, 24)//HeightTableCellConversation/2)) self.accessoryView = UIView(frame: accessoryViewFrame)// //for debug //cell.accessoryView?.backgroundColor = UIColor.greenColor() let updateTimeLabel = UILabel(frame: accessoryViewFrame) updateTimeLabel.textColor = ColorConversationAccessoryText updateTimeLabel.font = FontConversationAccessoryText updateTimeLabel.textAlignment = NSTextAlignment.Right self.accessoryView?.addSubview(updateTimeLabel) |
所以此处的:
cell.accessoryView!.subviews[0]
是有字视图,不会为空,不会出错的。
)
[总结]
已有要注意,对于类似于这样的代码:
if let prevHeaderImageView = cell.imageView?.subviews[0] { prevHeaderImageView.removeFromSuperview() } |
要写成:
if let imageViewSubViews = cell.imageView?.subviews{ if imageViewSubViews.count > 0 { let prevHeaderImageView = imageViewSubViews[0] prevHeaderImageView.removeFromSuperview() } } |
否则当
cell.imageView?.subviews
不为nil,但是却是empty的list的话,则
cell.imageView?.subviews[0]
就会报错了。。
转载请注明:在路上 » [已解决]Terminating app due to uncaught exception NSRangeException reason NSArray 0 objectAtIndex index 0 beyond bounds for empty NSArray