Reputation: 1352
Xcode 6.0.1, Swift iOS 8
I have what I think is a pretty trvial setup, but I am missing something that is causing issues, or is the default behaviour.
I have the following:
Tab Bar Controller -> Navigation Controller -> Table View Controller -Seque-> Table View Controller
I have the UIBarButtonItem 'Add' button (addPlayerInformationDetail) wired to the 2nd Table View Controller. The problem is when I push the controller via the segue, code runs on the wrong Table View Controller, and it crashes. I understand why it is crashing, but I don't understand why it's doing something on the 1st view controller. The 1st Table View Controller is also the NSFetchedResultsControllerDelegate.
The first Table View Controller (PlayerInformationTableViewController ) is using the standard Table View Controller boiler code. Here is the Segue calling the
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if debug==1 {
println("Running: ", reflect(self).summary.pathExtension,__FUNCTION__)
}
if segue.identifier == "addPlayerInformationDetail" {
//Nothing to do at the moment
} else if segue.identifier == "editPlayerInformationDetail" {
var indexPath:NSIndexPath = tableView.indexPathForSelectedRow()!
var vc = segue.destinationViewController as PlayerInformationDetailTableViewController
vc.managedObjectID = self.fetchedResultsController.objectAtIndexPath(indexPath).objectID
}
}
Here is the trace of all the methods and I pointed out where the code is going back to the 1st Table View Controller:
(Running: , AppDelegate, managedObjectContext)
(Running: , AppDelegate, persistentStoreCoordinator)
(Running: , AppDelegate, managedObjectModel)
(Running: , AppDelegate, applicationDocumentsDirectory)
(Running: , AppDelegate, application(_:didFinishLaunchingWithOptions:))
(Running: , PlayerInformationTableViewController, viewDidLoad())
(Running: , PlayerInformationTableViewController, viewWillAppear)
(Running: , PlayerInformationTableViewController, numberOfSectionsInTableView)
(Running: , PlayerInformationTableViewController, fetchedResultsController)
(Running: , PlayerInformationTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationTableViewController, fetchedResultsController)
(Running: , PlayerInformationTableViewController, numberOfSectionsInTableView)
(Running: , PlayerInformationTableViewController, fetchedResultsController)
(Running: , PlayerInformationTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationTableViewController, fetchedResultsController)
(Running: , AppDelegate, applicationDidBecomeActive)
(Running: , PlayerInformationTableViewController, prepareForSegue(_:sender:))
(Running: , PlayerInformationDetailTableViewController, putABorderAroundButtons())
(Running: , PlayerInformationDetailTableViewController, viewWillAppear)
(Running: , PlayerInformationDetailTableViewController, refreshInterface())
newPlayer (Function)
(Running: , PlayerInformationDetailTableViewController, newPlayer())
(Ending: , PlayerInformationDetailTableViewController, newPlayer())
Why is it going back to PlayerInformationTableViewController???
(Running: , PlayerInformationTableViewController, numberOfSectionsInTableView)
(Running: , PlayerInformationTableViewController, fetchedResultsController)
(Running: , PlayerInformationTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationTableViewController, fetchedResultsController)
(Running: , PlayerInformationDetailTableViewController, numberOfSectionsInTableView)
(Running: , PlayerInformationDetailTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationDetailTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationDetailTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationDetailTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationDetailTableViewController, numberOfSectionsInTableView)
(Running: , PlayerInformationDetailTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationDetailTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationDetailTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationDetailTableViewController, tableView(_:numberOfRowsInSection:))
(Running: , PlayerInformationTableViewController, tableView(_:cellForRowAtIndexPath:))
(Running: , PlayerInformationTableViewController, tableView(_:canEditRowAtIndexPath:))
(Running: , PlayerInformationTableViewController, configureCell(_:atIndexPath:))
(Running: , PlayerInformationTableViewController, fetchedResultsController)
After the Add button is tapped and (Ending: , PlayerInformationDetailTableViewController, newPlayer()) completes why is code in the PlayerInformationTableViewController running? I am adding a row into Core Data, but it shouldn't have anything to do with the NSFetchedResultsControllerDelegate in PlayerInformationTableViewController.
Here is the flow of Code in PlayerInformationDetailTableViewController
override func viewWillAppear(animated: Bool) {
if debug==1 {
println("Running: ", reflect(self).summary.pathExtension,__FUNCTION__)
}
refreshInterface()
}
func refreshInterface(){
if debug==1 {
println("Running: ", reflect(self).summary.pathExtension,__FUNCTION__)
}
if managedObjectID != nil {
println("existingPlayer \(existingPlayer)")
existingPlayer()
} else {
println("newPlayer \(newPlayer)")
newPlayer()
}
}
func newPlayer(){
if debug==1 {
println("Running: ", reflect(self).summary.pathExtension,__FUNCTION__)
}
//insert a new object in Core Data
var newPlayerInformation = NSEntityDescription.insertNewObjectForEntityForName("PlayerInformation", inManagedObjectContext: managedObjectContext!) as PlayerInformation
var newFirstName = playerInformationFirstNameTextField.text
var newLastName = playerInformationLastNameTextField.text
var newBirthPlace = playerInformationBirthPlaceTextField.text
newPlayerInformation.firstName = playerInformationFirstNameTextField.text
newPlayerInformation.lastName = playerInformationLastNameTextField.text
newPlayerInformation.birthPlace = playerInformationBirthPlaceTextField.text
if debug==1 {
println("Ending: ", reflect(self).summary.pathExtension,__FUNCTION__)
}
}
I hope I explained this properlly, as it's been really frustrating and I'm sure it's something simple I've missed. If I coment out // newPlayer() in func refreshInterface(), the code nevers goes back to PlayerInformationTableViewController. Thanks in advance. -PaulS.
Upvotes: 0
Views: 285
Reputation: 23078
The tracelog shows that your NSFetchedResultsController is detecting a change in its managedObjectContext, due to adding a new record. It immediately updates the related information numberOfRowsInSection
...
According to the NSFetchedResultsController Class Reference:
In addition, fetched results controllers provide the following features:
Optionally monitor changes to objects in the associated managed object context, and report changes in the results set to its delegate (see The Controller’s Delegate).
To disable this tracking the NSFetchedResultsController
's delegate should be set to nil
Upvotes: 1