我使用核心数据建立一对多关系,我的应用程序的场景是显示受尊敬团队的成员。团队和成员都是动态添加的。
将数据存储在成员部分时会出现问题。数据已存储但不会显示在表视图中。我在哪里得到这个错误。
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?
}
我非常困惑,如何为团队添加成员?!我怎么能解决这个问题?为了更好地理解这个场景,你可以参考这个问题Can I add an NSManagedObject to the selected parent object just using Interface Builder and Core Data?,你也可以参考这个https://github.com/pbasdf/DemoMasterDetail,这正是我希望我的应用程序产生输出的方式。
答案 0 :(得分:1)
嗨Praveen Kumar,你可以这样做:)
@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)
}
提示强>
关系船名应清楚地解释两个实体之间的联系。而不是简单地给出像成员一样的名字。团队制作了一个非常明智的名字:)
团队 - >包含 - >会员 成员 - > Belongs_To - >队
因此,团队实体应该将一对多关系发送给名为Contains的成员。因此,当人们看到并阅读时,团队将包含成员:)
同样,会员实体应该与名为Belongs_To的团队建立一对一关系。因此,当一个人看到它并读取它将成为属于团队的成员:))
希望我的回答能帮到你:)。