最新消息:20190717 VPS服务器:Vultr新加坡,WordPress主题:大前端D8,统一介绍入口:关于

[已解决]Terminating app due to uncaught exception NSRangeException reason NSArray 0 objectAtIndex index 0 beyond bounds for empty NSArray

Swift crifan 5196浏览 0评论

之前调试期间,一直不知道为何程序会挂掉:

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

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
17 queries in 0.098 seconds, using 9.42MB memory