在核心数据的一对多关系中,存储的数据无法显示在表格视图中?
我使用核心数据来build立一个一对多的关系,我的应用程序的场景是显示受尊敬的团队的成员。 dynamic添加团队和成员。
将数据存储在成员部分时发生此问题。 数据正在存储,但不会显示在表格视图中。 我得到这个错误。
data: { memberDesignation = ""; memberImage = nil; memberName = bbgbb; teams = nil; }) returned nil value for section name key path 'Teams.teams'. Object will be placed in unnamed section
因为我是核心数据的新手,所以我犯了一个愚蠢的错误。 我无法弄清楚我做错了什么。 我会告诉我做了什么,纠正我做错了什么。 请操纵我的代码,给我的答案,没有逻辑或随机答案,因为我没有足够的时间来尝试每一种可能性。非常感谢,提前感谢。
ER模型
团队表视图控制器
import UIKit import CoreData class GroupTable: UITableViewController, NSFetchedResultsControllerDelegate { let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext var teamData = [Teams]() var fetchedResultsController : NSFetchedResultsController = NSFetchedResultsController() let statusbarHeight: CGFloat = 20 override func numberOfSectionsInTableView(tableView: UITableView) -> Int { // #warning Incomplete implementation, return the number of sections return 1 } override func viewDidLoad() { super.viewDidLoad() tableView.contentInset.top = statusbarHeight self.navigationItem.leftBarButtonItem!.image = UIImage(named: "Arrow")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal) } @IBAction func backToLogo(sender: AnyObject) { let previous = self.storyboard?.instantiateViewControllerWithIdentifier("Logo") self.presentViewController(previous!, animated: true, completion: nil) } override func viewWillAppear(animated: Bool) { let request = NSFetchRequest(entityName: "Teams") do{ teamData = try managedObjectContext.executeFetchRequest(request) as! [Teams] } catch let error as NSError { print("\(error), \(error.userInfo)") } self.tableView.reloadData() } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if teamData.count > 0{ self.tableView.backgroundView = nil return teamData.count } else { let emptyLabel = UILabel(frame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)) emptyLabel.text = "No Teams available at the moment, create one!" emptyLabel.textAlignment = NSTextAlignment.Center self.tableView.backgroundView = emptyLabel self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None return 0 } } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("groupCell", forIndexPath: indexPath) let teamDetails = teamData[indexPath.row] cell.textLabel?.text = teamDetails.teamName cell.imageView?.image = teamDetails.teamImage as? UIImage return cell } override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // Get the new view controller using segue.destinationViewController. // Pass the selected object to the new view controller. if segue.identifier == "memberView" { let destination = segue.destinationViewController as! MemberTableViewController let indexPath = tableView.indexPathForSelectedRow! let selectedObject = fetchedResultsController.objectAtIndexPath(indexPath) as! Teams destination.currentTeam = selectedObject } } }
成员表视图控制器
import UIKit import CoreData class MemberTableViewController: UITableViewController, NSFetchedResultsControllerDelegate { let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext var memberData = [Members]() var currentTeam : Teams? var fetchedResultsController: NSFetchedResultsController! override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(animated: Bool) { let request = NSFetchRequest(entityName: "Members") let members = NSSortDescriptor(key: "memberName", ascending: false) request.sortDescriptors = [members] if let thisTeam = currentTeam { request.predicate = NSPredicate(format:"teams == %@",thisTeam) } let fetchedResults = NSFetchedResultsController(fetchRequest: request, managedObjectContext: managedObjectContext, sectionNameKeyPath: "Teams.members", cacheName: nil) fetchedResults.delegate = self do { try fetchedResults.performFetch() } catch { fatalError("Failed to initialize FetchedResultsController: \(error)") } self.tableView.reloadData() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source override func numberOfSectionsInTableView(tableView: UITableView) -> Int { // #warning Incomplete implementation, return the number of sections return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // #warning Incomplete implementation, return the number of rows if memberData.count > 0{ self.tableView.backgroundView = nil return memberData.count } else { let emptyLabel = UILabel(frame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)) emptyLabel.text = "No Members in the team, add one!" emptyLabel.textAlignment = NSTextAlignment.Center self.tableView.backgroundView = emptyLabel self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None return 0 } } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("memberCell", forIndexPath: indexPath) as! ScreenThreeTableViewCell // Configure the cell... let memberDetails = memberData[indexPath.row] cell.memberName?.text = memberDetails.memberName cell.memberDesignation?.text = memberDetails.memberDesignation cell.memberImage?.image = memberDetails.memberImage as? UIImage return cell } override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { } /* // Override to support conditional editing of the table view. override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { // Return false if you do not want the specified item to be editable. return true } */ /* // Override to support editing the table view. override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { if editingStyle == .Delete { // Delete the row from the data source tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) } else if editingStyle == .Insert { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } } */ /* // Override to support rearranging the table view. override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { } */ /* // Override to support conditional rearranging of the table view. override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { // Return false if you do not want the item to be re-orderable. return true } */ // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // Get the new view controller using segue.destinationViewController. // Pass the selected object to the new view controller. } }
添加小组
import UIKit import CoreData class ScreenTwoPopOverViewController: UIViewController, UIImagePickerControllerDelegate,UINavigationControllerDelegate,UIPopoverControllerDelegate { @IBOutlet weak var teamNamePO: UITextField! @IBOutlet weak var teamImagePO: UIImageView! @IBOutlet weak var selectPicturePO: UIButton! var picker:UIImagePickerController?=UIImagePickerController() let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func submit(sender: AnyObject) { let entity = NSEntityDescription.entityForName("Teams", inManagedObjectContext: managedObjectContext) let team = Teams(entity: entity!, insertIntoManagedObjectContext: managedObjectContext) team.teamName = teamNamePO.text team.teamImage = teamImagePO.image do{ try managedObjectContext.save() } catch let error as NSError{ print("\(error), \(error.userInfo)") } dismissViewControllerAnimated(true, completion: nil) } @IBAction func cancel(sender: AnyObject) { dismissViewControllerAnimated(true, completion: nil) } @IBAction func btnImagePickerClicked(sender: AnyObject) { let alert:UIAlertController=UIAlertController(title: "Choose Image", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet) let cameraAction = UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default) { UIAlertAction in self.openCamera() } let gallaryAction = UIAlertAction(title: "Gallary", style: UIAlertActionStyle.Default) { UIAlertAction in self.openGallary() } let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { UIAlertAction in } // Add the actions picker?.delegate = self alert.addAction(cameraAction) alert.addAction(gallaryAction) alert.addAction(cancelAction) // Present the controller self.presentViewController(alert, animated: true, completion: nil) } func openCamera() { if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) { picker!.sourceType = UIImagePickerControllerSourceType.Camera self .presentViewController(picker!, animated: true, completion: nil) }else { openGallary() } } func openGallary() { picker!.sourceType = UIImagePickerControllerSourceType.PhotoLibrary self.presentViewController(picker!, animated: true, completion: nil) } func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { picker .dismissViewControllerAnimated(true, completion: nil) teamImagePO.image=info[UIImagePickerControllerOriginalImage] as? UIImage } func imagePickerControllerDidCancel(picker: UIImagePickerController) { print("picker cancel.") self.presentViewController(self, animated: true, completion: nil) } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // Get the new view controller using segue.destinationViewController. // Pass the selected object to the new view controller. } */ }
添加成员
import UIKit import CoreData class ScreenThreePopOverViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UIPopoverControllerDelegate { @IBOutlet weak var memberDesignationPO: UITextField! @IBOutlet weak var memberNamePO: UITextField! @IBOutlet weak var memberImagePO: UIImageView! var picker:UIImagePickerController?=UIImagePickerController() let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext var currentTeam : Teams? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func selectPicture(sender: AnyObject) { let alert:UIAlertController=UIAlertController(title: "Choose Image", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet) let cameraAction = UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default) { UIAlertAction in self.openCamera() } let gallaryAction = UIAlertAction(title: "Gallary", style: UIAlertActionStyle.Default) { UIAlertAction in self.openGallary() } let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { UIAlertAction in } // Add the actions picker?.delegate = self alert.addAction(cameraAction) alert.addAction(gallaryAction) alert.addAction(cancelAction) // Present the controller self.presentViewController(alert, animated: true, completion: nil) } func openCamera() { if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) { picker!.sourceType = UIImagePickerControllerSourceType.Camera self .presentViewController(picker!, animated: true, completion: nil) }else { openGallary() } } func openGallary() { picker!.sourceType = UIImagePickerControllerSourceType.PhotoLibrary self.presentViewController(picker!, animated: true, completion: nil) } func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { picker .dismissViewControllerAnimated(true, completion: nil) memberImagePO.image=info[UIImagePickerControllerOriginalImage] as? UIImage } func imagePickerControllerDidCancel(picker: UIImagePickerController) { print("picker cancel.") dismissViewControllerAnimated(true, completion: nil) } @IBAction func cancel(sender: AnyObject) { dismissViewControllerAnimated(true, completion: nil) } @IBAction func submit(sender: AnyObject) { let entity = NSEntityDescription.entityForName("Members", inManagedObjectContext: managedObjectContext) let member = Members(entity: entity!, insertIntoManagedObjectContext: managedObjectContext) member.memberName = memberNamePO.text member.memberDesignation = memberDesignationPO.text member.memberImage = memberImagePO.image if let team = currentTeam { member.teams = team } do{ try managedObjectContext.save() } catch let error as NSError{ print("\(error), \(error.userInfo)") } dismissViewControllerAnimated(true, completion: nil) } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // Get the new view controller using segue.destinationViewController. // Pass the selected object to the new view controller. } */ }
团队实体
extension Teams { @NSManaged var teamImage: NSObject? @NSManaged var teamName: String? @NSManaged var members: NSSet? }
成员实体
extension Members { @NSManaged var memberDesignation: String? @NSManaged var memberImage: NSObject? @NSManaged var memberName: String? @NSManaged var teams: Teams? }
我非常困惑,如何join队伍方面的成员?! 我怎么解决这个问题? 为了更好的理解这个场景,你可以参考这个问题。我可以使用Interface Builder和Core Data将NSManagedObject添加到选定的父对象吗? 也可以参考这个https://github.com/pbasdf/DemoMasterDetail ,这正是我希望我的应用程序产生输出。
嗨Praveen库马尔你可以做这样的事情:)
@IBAction func submit(sender: AnyObject) { let entity = NSEntityDescription.entityForName("Members", inManagedObjectContext: managedObjectContext) let member = Members(entity: entity!, insertIntoManagedObjectContext: managedObjectContext) member.memberName = memberNamePO.text member.memberDesignation = memberDesignationPO.text member.memberImage = memberImagePO.image member.setValue(currentTeam, forKey: "teams") //mistake you did is you were trying to set the wrong relationship :) member has a relationship to teams and is called teams. So you can access member.teams not member.members //or member.teams = currentTeam do{ try managedObjectContext.save() } catch let error as NSError{ print("\(error), \(error.userInfo)") } dismissViewControllerAnimated(true, completion: nil) }
小费
关系船名应清楚地解释两个实体之间的联系。 而不是简单地给名称,如成员和团队,使一个很明智的名字:)
团队 – >包含 – >成员 – >属于 – >团队
所以团队实体应该有一对多的关系到名为Contains的成员。 所以当一个人看到它,并读取它将是团队成员:)
同样,会员实体应该与名为Belongs_To的团队有一对一的关系。 所以当一个人看到它,并读取它将成员属于团队:)
希望我的回答帮助你:)