带有 Segues、Core Data 和 Swift 的 UITableViewController 的问题

Posted

技术标签:

【中文标题】带有 Segues、Core Data 和 Swift 的 UITableViewController 的问题【英文标题】:Issues with UITableViewController with Segues, Core Data and Swift 【发布时间】:2014-10-06 11:48:58 【问题描述】:

Xcode 6.0.1,Swift ios 8

我有一个我认为非常简单的设置,但我遗漏了一些导致问题的东西,或者是默认行为。

我有以下:

Tab Bar Controller -> Navigation Controller -> Table View Controller -Seque-> Table View Controller

我将 UIBarButtonItem“添加”按钮 (addPlayerInformationDetail) 连接到第二个表视图控制器。问题是当我通过 segue 推送控制器时,代码在错误的表视图控制器上运行,并且它崩溃了。我理解它为什么会崩溃,但我不明白它为什么在第一个视图控制器上做某事。第一个表视图控制器也是 NSFetchedResultsControllerDelegate。

第一个 Table View Controller (PlayerInformationTableViewController) 使用标准的 Table View Controller 锅炉代码。这是 Segue 调用的

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
    

这是所有方法的踪迹,我指出了代码返回到第一个表视图控制器的位置:

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

点击 Add 按钮后 (Ending: , PlayerInformationDetailTableViewController, newPlayer()) 完成后为什么 PlayerInformationTableViewController 中的代码在运行?我在 Core Data 中添加了一行,但它不应该与 PlayerInformationTableViewController 中的 NSFetchedResultsControllerDelegate 有任何关系。

这是PlayerInformationDetailTableViewController中的代码流程

覆盖 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__)
    

我希望我能正确解释这一点,因为这真的很令人沮丧,而且我确信这是我错过的一些简单的事情。如果我在 func refreshInterface() 中注释掉 //newPlayer(),则代码永远不会返回到 PlayerInformationTableViewController。提前致谢。 -PaulS。

【问题讨论】:

【参考方案1】:

跟踪日志显示您的 NSFetchedResultsController 正在检测其 managedObjectContext 中的更改,因为添加了一条新记录。立即更新相关信息numberOfRowsInSection...

根据NSFetchedResultsController Class Reference:

此外,获取的结果控制器还提供以下功能:

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

要禁用此跟踪,NSFetchedResultsController 的委托应设置为 nil

【讨论】:

我应该在何时/何处将NSFetchedResultsController 的委托设置为nil,在我的segue 中? NSFetchedResultsController 通知您的PlayerInformationTableViewController 必须更新表数据。这是一种合乎逻辑的行为。您必须检查代码崩溃的原因。 虽然这不是答案,但它为我指明了正确的方向,可以在我的代码中找到一些逻辑错误。我的问题是我在输入数据之前向我的数据库中插入了一条新记录,因此我的数据总是为零。问题解决了。谢谢

以上是关于带有 Segues、Core Data 和 Swift 的 UITableViewController 的问题的主要内容,如果未能解决你的问题,请参考以下文章

带有 Core Data 和 Restkit 的多个视图控制器

显示带有来自 Core Data 的布尔值的 .sheet

使用带有 Core Data 的脏标志与服务器同步

如何使用带有 Swift 的 Core Data 获取非标准(可转换)属性来更新/保存和持久化?

程序接收信号:带有Core Data的“EXC_BAD_ACCESS”

手动和非自适应手动 Segues