__pthread_kill on second request

2019-08-04 07:52发布

问题:

I am getting json array response from particular url
On first request every thing is working fine but when second request goes then application crashes.

libsystem_kernel.dylib`__pthread_kill: 0x1082f885c: movl $0x2000148, %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)

I have following code

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
}
}

回答1:

It's pretty clear error message, just read it. Quote:

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).

It says:

  • after the update (insert/delete) you've got 1 cell in section 0,
  • but before you did update the table view, you had 11 cells there, then you did insert 1 cell, thus it expects 11+1 cells, not 1

Problem is that number of cells in section 0 equals to nameData.count. And your code (removed unrelated parts) ...

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)
}

... removes all objects from self.nameData, but not from table view.

Table view cells and your backing store is not synced.

Reload Data

Remove self.tableView.insert... line and place self.tableView.reloadData() just after the for loop. It reloads the whole table view.

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()

Or reload just one section.

func reloadSections(_ sections: NSIndexSet)

Delete Items & Then Insert

If you do not want to reload all cells (whole table view), you must keep in mind that your backing store for data must be kept in sync with table view. In other words - if you do remove cell from table view, you must remove it from your backing store. If you do insert cell into table view, you must insert it into backing store. And vice versa.

In your case, you call self.nameData.removeAllObjects(), but you didn't delete table view cells for these objects. You should call ...

func deleteItemsAtIndexPaths(_ indexPaths: [NSIndexPath])

... on self.tableView for all objects you did remove from self.nameData.

If you do lot of deleteItems.../insertItems/... calls, it's good to wrap them in performBatchUpdates(_:completion:):

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

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