最新消息:20210917 已从crifan.com换到crifan.org

[已解决]swift中已更新对应行的数据源但tableView的reloadRowsAtIndexPaths却还是出错崩溃:attempt to delete row 0 from section 0 which only contains 0 rows before the update

Swift crifan 6643浏览 0评论

[背景]

代码:

let newInsertItemIdx:Int = 0
let firstItemIndexPath:NSIndexPath = NSIndexPath(forRow: newInsertItemIdx, inSection: 0)
self.tableView.reloadRowsAtIndexPaths([firstItemIndexPath], withRowAnimation: UITableViewRowAnimation.Automatic)

出错:

2015-12-02 15:28:37.409 JianDao[18264:1143873] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.29.5/UITableView.m:1426
2015-12-02 15:28:44.998 JianDao[18264:1143873] *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘attempt to delete row 0 from section 0 which only contains 0 rows before the update’
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000110a65f45 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010fcfedeb objc_exception_throw + 48
    2   CoreFoundation                      0x0000000110a65daa +[NSException raise:format:arguments:] + 106
    3   Foundation                          0x000000010f94b5ee -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 198
    4   UIKit                               0x000000011169b19b -[UITableView _endCellAnimationsWithContext:] + 4799
    5   JianDao                             0x000000010f3ae3d3 _TFFC7JianDao26ConversationViewController22addNewConversationItemFS0_FCS_16ConversationItemT_U_FT_T_ + 675
    6   JianDao                             0x000000010f389bd7 _TTRXFo__dT__XFdCb__dT__ + 39
    7   libdispatch.dylib                   0x00000001133dce5d _dispatch_call_block_and_release + 12
    8   libdispatch.dylib                   0x00000001133fd49b _dispatch_client_callout + 8
    9   libdispatch.dylib                   0x00000001133e52af _dispatch_main_queue_callback_4CF + 1738
    10  CoreFoundation                      0x00000001109c62e9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    11  CoreFoundation                      0x00000001109878a9 __CFRunLoopRun + 2073
    12  CoreFoundation                      0x0000000110986e08 CFRunLoopRunSpecific + 488
    13  GraphicsServices                    0x0000000115106ad2 GSEventRunModal + 161
    14  UIKit                               0x000000011157530d UIApplicationMain + 171
    15  JianDao                             0x000000010f355f2d main + 109
    16  libdyld.dylib                       0x000000011343192d start + 1
    17  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

objective c – NSInternalInconsistencyException’, reason: ‘attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update’ – Stack Overflow

iphone – Crash on reloadRowsAtIndexPath but not on reloadData – Stack Overflow

ios – "Attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update" Error – Stack Overflow

Reloading the Table View – UITableView Class Reference

reloadData()

Reloads the rows and sections of the table view.

Declaration

SWIFT

func reloadData()

Discussion

Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view’s delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates and endUpdates.

感觉是:

应该把此处的:

reloadRowsAtIndexPaths

换成

reloadData

-》因为此处是datasource中的data变化了。

-》所以不应该调用reloadRowsAtIndexPaths,而应该直接用reloadData???

-》但是不会导致效率很低吗?

有点看懂了:

此处是:

对于tableView的datasource的数组:

conversationItemList

最开始conversationItemList是空的,count是0

此处之前已经调用了:

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
       
print("ConversationViewController numberOfRowsInSection")
       
return conversationItemList.count
    }

所以当时是numberOfRowsInSection返回的是0

而此处虽然是已经添加数据了:

        if conversationItemList.count == 0 {
           
conversationItemList.append(newConversationItem)
        }
       
else {
           
conversationItemList.insert(newConversationItem, atIndex: newInsertItemIdx)
        }

但是此时tableView并不知道你的数据源变化了

-》所以此时调用reloadRowsAtIndexPaths,发现:

section 0中,并没有数据

而reload需要

先删除delete

再添加add

所以此时delete不存在的row的话,就报错了。

-》所以,此处应该是先调用reloadData

-》让系统知道数据变化了。

iphone – Crash on reloadRowsAtIndexPath but not on reloadData – Stack Overflow

中的解释,也和我猜的一样:

“I know that it has been a while since this question was asked but I think the problem might be that, reloadRowsAtIndexPaths relies on the prior existence of those rows in the table and internally deletes, recreates and inserts them back in (under the hood). So when you are calling the specific reload without those rows already being in the table, it is trying to delete a row that is not there.

I came across the same problem with a collection view. The reason why a full reload works is because it refreshes the whole thing and does not rely on prior state, only on the current condition of your data source.

This is my take on the problem.”

[总结]

所以结论很简单:

当你之前的对应的row中的cell并存在的话

(注意:即使你数据源中的list中已经刚(通过insert或append)添加了对应的数据,但是却没有调用reloadData的话,对应的UI界面中的UITableViewCell还是不存在的)

则此时调用reloadRowsAtIndexPaths,就会出错:

因为:

reloadRowsAtIndexPaths是依赖于之前的状态的

之前的状态是还不存在对应的UITableViewCell

reloadRowsAtIndexPaths需要先去delete对应的cell,然后再去重新添加对应的cell的

解决办法是:

在添加了数据源中对应的行的数据后,先去调用reloadData

(其实也就不需要:再去调用reloadRowsAtIndexPaths)了。。。

转载请注明:在路上 » [已解决]swift中已更新对应行的数据源但tableView的reloadRowsAtIndexPaths却还是出错崩溃:attempt to delete row 0 from section 0 which only contains 0 rows before the update

发表我的评论
取消评论

表情

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

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
93 queries in 0.188 seconds, using 20.11MB memory