核心数据一对多关系不存储其数据

时间:2016-03-04 06:48:15

标签: ios entity-framework sqlite core-data swift2

我有一个基于表视图的应用程序,它有一个MasterTableViewController和一个DetailChildTableViewController。

MasterTableViewController在导航栏中有一个+,因此会向用户显示一个视图,以便在文本字段中输入该文件夹的名称。用户完成后,完成时钟,然后使用Core Data存储此文件夹,并在MasterTableViewController中显示此新文件夹。

以下是此特定TableViewController的代码

MasterTableViewController

   class MasterTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {


let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var fetchedResultsController : NSFetchedResultsController = NSFetchedResultsController()

// Populate fetched results controller
func getFetchedResultController() -> NSFetchedResultsController {

    fetchedResultsController = NSFetchedResultsController(fetchRequest: taskFetchRequest(), managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

    return fetchedResultsController

}


func taskFetchRequest() -> NSFetchRequest {

    let fetchRequest = NSFetchRequest(entityName: "Folder")
    let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)


    fetchRequest.sortDescriptors = [sortDescriptor]
    return fetchRequest
}


}
override viewDidLoad(){
fetchedResultsController = getFetchedResultController()
    fetchedResultsController.delegate = self
    do {
        try fetchedResultsController.performFetch()
    } catch _ {
    }
 }

 // Table View Methods to show data in Custom UITableViewCell and Segue method....

此控制器中的其余代码只有方法在表视图单元格中显示数据,以及segue方法,当用户点击新创建的单元格对象时,该方法将Core Data名称传递给下一个视图控制器。

以下是创建此特定对象以在MasterTableViewController上保存和显示的代码

AddViewController

class addItemTableViewController: UITableViewController {

@IBOutlet weak var FolderName: UITextField!

// Use the same managed object to save

let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

 @IBAction func Done(sender: AnyObject){

 // Calling a function to save the folder to core data
 saveFolder()
 self.dismissViewControllerAnimated(true, completion: nil)
 }

// Function that saves

func saveFolder(){
 let entityDescription = NSEntityDescription.entityForName("Folder", inManagedObjectContext: managedObjectContext)
    let item = Folder(entity: entityDescription!, insertIntoManagedObjectContext: managedObjectContext)

    item.name = FolderName.text!


    // Passed Value of the color picker table view below


    do {
        try managedObjectContext.save()
        print("Successfully Saved \n")
    } catch _ {
    }
}

}

因此,此代码基本上保存了新输入的文件夹并解除了文件夹名称视图,并且MasterTableViewController显示了这个新文件夹。

问题在于 DetailChildTableViewController ,其中是在MasterTableViewController中创建的每个文件夹的详细信息。

以下是最终tableview Controller的代码

** DetailChildTableViewController **

   class DetailChildTableViewController: UITableViewController, UIPopoverPresentationControllerDelegate, NSFetchedResultsControllerDelegate {

let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

var fetchedResultsController : NSFetchedResultsController = NSFetchedResultsController()

// Populate fetched results controller
func getFetchedResultController() -> NSFetchedResultsController {

    fetchedResultsController = NSFetchedResultsController(fetchRequest: taskFetchRequest(), managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

    return fetchedResultsController

}


func taskFetchRequest() -> NSFetchRequest {

    let fetchRequest = NSFetchRequest(entityName: "List")
    let sortDescriptor = NSSortDescriptor(key: "itemListName", ascending: false)


    fetchRequest.sortDescriptors = [sortDescriptor]
    return fetchRequest
}

 override func viewDidLoad() {
    super.viewDidLoad(){

    // Core data
    fetchedResultsController = getFetchedResultController()
    fetchedResultsController.delegate = self
    do {
        try fetchedResultsController.performFetch()
    } catch _ {
    }

    self.tableView.reloadData()

}

 // MARK: - Display the results in table view

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

    if let sections = fetchedResultsController.sections {
        return sections.count
    }

    return 0
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if let sections = fetchedResultsController.sections {
        let currentSection = sections[section]
        return currentSection.numberOfObjects
    }

    return 0
}

}

此DetailChildTableViewController在导航栏中还有一个+按钮,并显示一个类似的AddViewController,使用相同的Core Data方法将数据添加到此特定文件夹。

问题在于,当我在MasterTableViewController中创建2个实体时,例如:

  • Folder_One
  • Folder_Two

然后我进入 Folder_Two 并在此文件夹中创建一个列表对象,然后返回到MasterTableViewController,然后选择 Folder_One ,它仍显示相同的列表对象我在 Folder_Two 中创建。

我如何处理这个简单但不明确的问题的解决方案?

顺便说一下,这是我的数据模型:

TestApp.xcdatamodel

实体:

  1. 文件夹
  2. 列表

    Atributes: String类型的名称(适用于文件夹实体) String类型的 itemListName (对于列表实体)

    关系:(对于文件夹实体) relation destination :List

  3. 请注意,List实体未列为与Folder有关系。我将文件夹设置为与列表的关系为一对多关系。

    我做错了什么,我该如何处理?

1 个答案:

答案 0 :(得分:1)

问题是您的DetailChildTableViewController显示所有 List个对象。您需要将其限制为仅提取与当前List相关的Folder个对象。为此,您必须拥有从ListFolder的关系。这种关系将是一对一,并且将是从FolderList的多对多关系的倒数。 (你应该几乎总是为每个关系创建一个逆。即使你觉得你不需要它,无论如何都要创建它。在这种情况下,正如你将在下面看到的,你确实需要它)。所以你的实体模型应该是这样的:

Folder          List
======          ====
name            itemListName
lists <------>> folder

DetailChildTableViewController中,添加一个新变量,该变量将显示Folder的{​​{1}}:

Lists

要限制抓取以使其仅显示与此文件夹相关的var currentFolder : Folder? 个对象,请在抓取请求中添加谓词:

List

当用户点击if let thisFolder = currentFolder { fetchRequest.predicate = NSPredicate(format:"folder == %@",thisFolder) } 中的单元格时,在显示MasterTableViewController之前,您必须为DetailChildTableViewController设置正确的值。在currentFolder中,您需要以下内容:

prepareForSegue

同样,let indexPath = self.tableView.indexPathForSelectedRow! let currentFolder = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Folder detailViewController.currentFolder = currentFolder 必须有AddListViewController变量才能知道新创建的currentFolder应属于哪个Folder(以及List中的代码segv到它必须设置DetailChildTableViewController)的值。在currentFolder中,当您存储AddListViewController项时,您需要设置关系:

List

请注意,当您设置关系时,CoreData会自动设置反向关系(假设您定义了一个)。因此,newList.folder = currentFolder 将添加到newList的{​​{1}}属性。