__pthread_kill 根据第二次请求

__pthread_kill on second request

我从特定的 url
得到 json 数组响应 在第一次请求时一切正常,但是当第二次请求出现时应用程序崩溃。

libsystem_kernel.dylib`__pthread_kill: 0x1082f885c: movl [=12=]x2000148, %eax 0x1082f8861: movq %rcx, %r10 0x1082f8864: syscall 0x1082f8866: jae 0x1082f8870 ; __pthread_kill + 20 0x1082f8868: movq %rax, %rdi 0x1082f886b: jmp 0x1082f5175 ; cerror_nocancel 0x1082f8870: retq
0x1082f8871: nop
0x1082f8872: nop
0x1082f8873: nop



StackTrace

2015-07-16 13:44:37.126 Contact Book[15714:106637] * Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3318/UITableView.m:1582 2015-07-16 13:44:37.341 Contact Book[15714:106637] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (11), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).' *** First throw call stack: ( 0 CoreFoundation 0x0000000105cd53f5 exceptionPreprocess + 165 1 libobjc.A.dylib 0x0000000107803bb7 objc_exception_throw + 45 2 CoreFoundation 0x0000000105cd525a +[NSException raise:format:arguments:] + 106 3 Foundation 0x000000010616c28f -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195 4 UIKit 0x000000010663346a -[UITableView _endCellAnimationsWithContext:] + 11746 5 Contact Book 0x0000000105ae6a11 _TFFC12Contact_Book20MasterViewController38updateSearchResultsForSearchControllerFS0_FCSo18UISearchControllerT_U_FTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError__T_ + 2625 6 Contact Book 0x0000000105ae6bb3 _TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFo_iTGSQS__GSQS0__GSQS1____iT + 51 7 Contact Book 0x0000000105ae4091 _TPA__TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFo_iTGSQS__GSQS0__GSQS1____iT__ + 81 8 Contact Book 0x0000000105ae6e83 _TTRXFo_iTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError___iT__XFo_oGSQS__oGSQS0__oGSQS1___dT__ + 35 9 Contact Book 0x0000000105ae6f0f _TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFdCb_dGSQS__dGSQS0__dGSQS1___dT__ + 127 10 CFNetwork 0x0000000108aaebbb 49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 157 11 Foundation 0x000000010618fccf __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK + 7 12 Foundation 0x00000001060cfb32 -[NSBlockOperation main] + 98 13 Foundation 0x00000001060b2104 -[__NSOperationInternal _start:] + 645 14 Foundation 0x00000001060b1d13 __NSOQSchedule_f + 184 15 libdispatch.dylib 0x0000000107fa87f4 _dispatch_client_callout + 8 16 libdispatch.dylib 0x0000000107f90bf4 _dispatch_queue_drain + 1417 17 libdispatch.dylib 0x0000000107f90506 _dispatch_queue_invoke + 235 18 libdispatch.dylib 0x0000000107f92ff7 _dispatch_root_queue_drain + 682 19 libdispatch.dylib 0x0000000107f9463c _dispatch_worker_thread2 + 52 20 libsystem_pthread.dylib 0x000000010833eef8 _pthread_wqthread + 314 21 libsystem_pthread.dylib 0x0000000108341fb9 start_wqthread + 13 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)

我有以下代码

import UIKit

class MasterViewController: UITableViewController,     UISearchControllerDelegate, UISearchResultsUpdating, UISearchBarDelegate  {

var completeData = NSMutableArray()
var nameData = NSMutableArray()


override func awakeFromNib() {
    super.awakeFromNib()
}


var searchController : UISearchController!

override func viewDidLoad() {
    super.viewDidLoad()

    self.searchController = UISearchController(searchResultsController:  nil)

    self.searchController.searchResultsUpdater = self
    self.searchController.delegate = self
    self.searchController.searchBar.delegate = self

    self.searchController.hidesNavigationBarDuringPresentation = false
    self.searchController.dimsBackgroundDuringPresentation = true
    self.navigationItem.titleView = searchController.searchBar

    self.definesPresentationContext = true
}
    var flag = false
    var task: NSURLSessionTask!

func updateSearchResultsForSearchController(searchController: UISearchController) {
    var inputText = searchController.searchBar.text as NSString

    if inputText.length > 3 {
        //TODO repalce space by %20

        if flag{
            task.cancel()}

        let url = NSURL(string: "http://172.26.1.39:8080/ContactBook/search?term="+inputText);

        task = NSURLSession.sharedSession().dataTaskWithURL(url){(data, response, error) in

            if(error != nil){
                println("SOME ERROR")
                return
            }

            var parseError: NSError?

            var jsonArray = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &parseError) as NSArray

            if parseError != nil {
                println("something wrong")
                return
            }


            self.completeData.removeAllObjects()
            self.nameData.removeAllObjects()

            var tempObject : NSDictionary;

            for var i=0; i < jsonArray.count; i++ {
                var jsonDict = jsonArray[i] as NSDictionary
                self.completeData.insertObject(jsonDict, atIndex: 0)
                var name = jsonDict.valueForKey("name")! as NSString
                self.nameData.insertObject(name, atIndex: 0)
                let indexPath = NSIndexPath(forRow: 0, inSection: 0)
                self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
            }
        }
        flag = true
        task.resume()
    }
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Segues

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showDetail" {
        if let indexPath = self.tableView.indexPathForSelectedRow() {
            let object = completeData[indexPath.row] as NSDictionary
            (segue.destinationViewController as DetailViewController).detailItem = object
        }
    }
}

// MARK: - Table View

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return nameData.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
    let object = nameData[indexPath.row] as NSString
    cell.textLabel?.text = object.description
    return cell
}

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return false
}
}

错误信息很清楚,读一读。引用:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (11), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).

它说:

  • 更新后 (insert/delete) 您在第 0 节中有 1 个单元格,
  • 但在更新 table 视图之前,那里有 11 个单元格,然后插入了 1 个单元格,因此它需要 11+1 个单元格,而不是 1

问题是 0 部分中的单元格数等于 nameData.count。还有你的代码(删除了不相关的部分)...

self.nameData.removeAllObjects()   <----- (delete)

var tempObject : NSDictionary;

for var i=0; i < jsonArray.count; i++ {
  var jsonDict = jsonArray[i] as NSDictionary
  var name = jsonDict.valueForKey("name")! as NSString
  self.nameData.insertObject(name, atIndex: 0) <----- (insert)
  let indexPath = NSIndexPath(forRow: 0, inSection: 0)
  self.tableView.insertRowsAtIndexPaths([indexPath],
    withRowAnimation: .Fade)  <------ (insert)
}

... 从 self.nameData 中删除所有对象,但不从 table 视图中删除所有对象。

Table 查看单元格和您的后备存储未同步。

重新加载数据

删除 self.tableView.insert... 行并将 self.tableView.reloadData() 放在 for 循环之后。它会重新加载整个 table 视图。

self.nameData.removeAllObjects()

var tempObject : NSDictionary;

for var i=0; i < jsonArray.count; i++ {
  var jsonDict = jsonArray[i] as NSDictionary
  var name = jsonDict.valueForKey("name")! as NSString
  self.nameData.insertObject(name, atIndex: 0)
  let indexPath = NSIndexPath(forRow: 0, inSection: 0)
}
self.tableView.reloadData()

或者只重新加载一个部分。

func reloadSections(_ sections: NSIndexSet)

删除项目然后插入

如果您不想重新加载所有单元格(整个 table 视图),您必须牢记数据的后备存储必须与 table 视图保持同步。换句话说 - 如果您确实从 table 视图中删除单元格,则必须将其从后备存储中删除。如果将单元格插入 table 视图,则必须将其插入后备存储。反之亦然。

在您的情况下,您调用了 self.nameData.removeAllObjects(),但是您没有删除这些对象的 table 视图单元格。你应该打电话给...

func deleteItemsAtIndexPaths(_ indexPaths: [NSIndexPath])

... self.tableView 对于您从 self.nameData.

移除的所有对象

如果你进行了很多 deleteItems.../insertItems/... 调用,最好将它们包装在 performBatchUpdates(_:completion:):

func performBatchUpdates(_ updates: (() -> Void)?,
  completion completion: ((Bool) -> Void)?)

Animates multiple insert, delete, reload, and move operations as a group.