tableView.insertRows throws NSException, but not when `insertRows` at `[[0,0]]`
我正在关注本教程的修改(简化)版本,非常类似于此处的内容:
https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/ImplementNavigation.html#//apple_ref/doc/uid/TP40015214-CH16-SW1
这是我的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | import UIKit class NewsTableViewController: UITableViewController { @IBOutlet var newsTableView: UITableView! /* MARK: properties */ var news = NewsData() override func viewDidLoad() { super.viewDidLoad() dummyNewData() } // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return news.length() } // here we communicate with parts of the app that owns the data override func tableView(_ tableView: UITableView , cellForRowAt indexPath: IndexPath ) -> UITableViewCell { // note here we're using the native cell class let cell = tableView.dequeueReusableCell(withIdentifier:"newsCell", for: indexPath) // Configure the cell... let row : Int = indexPath.row cell.textLabel?.text = news.read(idx: row) return cell } // MARK: Navigation **************************************************************** // accept message from CreateNewViewController @IBAction func unwindToCreateNewView(sender: UIStoryboardSegue){ if let srcViewController = sender.source as? CreateNewsViewController , let msg = srcViewController.message { // push into news instance and display on table news.write(msg: msg) let idxPath = IndexPath(row: news.length(), section: 1) // tableView.insertRows(at: [idxPath], with: .automatic) tableView.insertRows(at: [[0,0]], with: .automatic) print("unwound with message:", msg, idxPath) print("news now has n pieces of news:", news.length()) print("the last news is:", news.peek()) } } /* @DEBUG: debugging functions that display things on screen ************************** */ // push some values into new data private func dummyNewData(){ print("dummyNewData") news.write(msg:"hello world first message") news.write(msg:"hello world second message") news.write(msg:"hello world third message") } } |
问题出在函数
1 2 | let idxPath = IndexPath(row: news.length(), section: 1) tableView.insertRows(at: [idxPath], with: .automatic) |
其中
当我
1 | libc++abi.dylib: terminating with uncaught exception of type NSException |
但是当我只是硬编码它时:
1 | tableView.insertRows(at: [[0,0]], with: .automatic) |
它工作得很好。在模拟器上,我看到新消息插入到以前的消息下方。什么给了?
下面的代码有一个"off by one"问题:
1 2 | news.write(msg: msg) let idxPath = IndexPath(row: news.length(), section: 1) |
假设在调用这段代码之前,
调用
调用
一个简单的解决方案是交换这两行:
1 2 | let idxPath = IndexPath(row: news.length(), section: 1) news.write(msg: msg) |
这将创建具有正确行号的索引路径。
而且由于这是第一个(也是唯一一个)节,除了上述更改之外,节号还需要更改为 0。
1 2 | let idxPath = IndexPath(row: news.length(), section: 0) news.write(msg: msg) |