我正在构建一个具有两个CoreData实体 - 锻炼和练习的应用程序。两者之间的关系是多对多的。Swift - 为相关CoreData实体分配值
该应用程序是一对基本的tableViewController,允许您将锻炼(workoutName)添加到锻炼实体,然后将锻炼添加到下一个tableViewController中的锻炼。我正在努力的是如何将每个练习重新分配给它在CoreData中产生的锻炼。基本上,我试图做的是在练习实体中添加newExercise(使用exerciseName变量)时,在Workouts实体中设置workoutName值。
我将workoutName作为锻炼tableViewController的锻炼传递给锻炼tableViewController作为var锻炼。
我也有多对多的关系,并在NSManagedObjects文件中设置为NSSets,但不知道如何使用它们。
下面是行使tableViewController设置:
import UIKit
import CoreData
class ExerciseMasterTableViewController: UITableViewController {
// Declare workout variable
var workout: Workouts!
// Create an empty array of Exercises
var exercises = [Exercises]()
// Retreive the managedObjectContext from AppDelegate
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
override func viewDidLoad() {
super.viewDidLoad()
// Use optional binding to confirm the managedObjectContext
if let moc = self.managedObjectContext {
}
fetchExercises()
}
func fetchExercises() {
let fetchRequest = NSFetchRequest(entityName: "Exercises")
// Create a sort descriptor object that sorts on the "exerciseName"
// property of the Core Data object
let sortDescriptor = NSSortDescriptor(key: "exerciseName", ascending: true)
// Set the list of sort descriptors in the fetch request,
// so it includes the sort descriptor
fetchRequest.sortDescriptors = [sortDescriptor]
if let fetchResults = managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [Exercises] {
exercises = fetchResults
}
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// How many rows are there in this section?
// There's only 1 section, and it has a number of rows
// equal to the number of exercises, so return the count
return exercises.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Exercise Cell", forIndexPath: indexPath) as UITableViewCell
// Get the Exercises for this index
let exercise = exercises[indexPath.row]
// Set the title of the cell to be the title of the exercise
cell.textLabel!.text = exercise.exerciseName
cell.detailTextLabel!.text = "\(exercise.sets)x\(exercise.reps)"
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
return cell
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if(editingStyle == .Delete) {
// Find the Exercise object the user is trying to delete
let exerciseToDelete = exercises[indexPath.row]
// Delete it from the managedObjectContext
managedObjectContext?.deleteObject(exerciseToDelete)
// Refresh the table view to indicate that it's deleted
self.fetchExercises()
// Tell the table view to animate out that row
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
save()
}
}
// MARK: UITableViewDelegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let exercise = exercises[indexPath.row]
}
let addExerciseAlertViewTag = 0
let addExerciseTextAlertViewTag = 1
@IBAction func addExerciseButton(sender: AnyObject) {
var namePrompt = UIAlertController(title: "Add Exercise",
message: "Enter Exercise Name",
preferredStyle: .Alert)
var exerciseNameTextField: UITextField?
namePrompt.addTextFieldWithConfigurationHandler {
(textField) -> Void in
exerciseNameTextField = textField
textField.placeholder = "Exercise Name"
}
namePrompt.addAction(UIAlertAction(title: "Ok",
style: .Default,
handler: { (action) -> Void in
if let textField = exerciseNameTextField {
self.saveNewItem(textField.text, workoutName: workouts.workoutName)
}
}))
self.presentViewController(namePrompt, animated: true, completion: nil)
}
func saveNewItem(exerciseName : String, workoutName: String) {
// Create the new exercise item
var newExercise = Exercises.createExerciseInManagedObjectContext(self.managedObjectContext!, exerciseName: exerciseName, workoutName: workoutName)
// Update the array containing the table view row data
self.fetchExercises()
// Animate in the new row
// Use Swift's find() function to figure out the index of the newExercise
// after it's been added and sorted in our Exercises array
if let newExerciseIndex = find(exercises, newExercise) {
// Create an NSIndexPath from the newExerciseIndex
let newExerciseIndexPath = NSIndexPath(forRow: newExerciseIndex, inSection: 0)
// Animate in the insertion of this row
tableView.insertRowsAtIndexPaths([ newExerciseIndexPath ], withRowAnimation: .Automatic)
save()
}
}
func save() {
var error : NSError?
if(managedObjectContext!.save(&error)) {
println(error?.localizedDescription)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "exerciseSettings" {
let ExerciseSettingsDetailViewController = segue.destinationViewController as UIViewController
let indexPath = tableView.indexPathForSelectedRow()!
let exercise = exercises[indexPath.row]
let destinationTitle = exercise.exerciseName
ExerciseSettingsDetailViewController.title = destinationTitle
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
而且,这里是我的练习类中定义添加newExercise功能createExerciseInManagedObjectContext:
class func createExerciseInManagedObjectContext(moc: NSManagedObjectContext, exerciseName: String, workoutName: String) -> Exercises {
let newExercise = NSEntityDescription.insertNewObjectForEntityForName("Exercises", inManagedObjectContext: moc) as Exercises
newExercise.exerciseName = exerciseName
self.workouts.addObject(workoutName)
return newExercise
}
我可以传递将所选锻炼(锻炼名称)的字符串添加到此功能中,但不知道如何通过与锻炼实体的锻炼关系进行设置。
这里是我的练习实体:
import Foundation
import CoreData
class Exercises: NSManagedObject {
@NSManaged var exerciseName: String
@NSManaged var sets: NSNumber
@NSManaged var reps: NSNumber
@NSManaged var repWeight: NSNumber
@NSManaged var barWeight: NSNumber
@NSManaged var incrementWeight: NSNumber
@NSManaged var workouts: NSSet
class func createExerciseInManagedObjectContext(moc: NSManagedObjectContext, exerciseName: String, workoutName: String) -> Exercises {
let newExercise = NSEntityDescription.insertNewObjectForEntityForName("Exercises", inManagedObjectContext: moc) as Exercises
newExercise.exerciseName = exerciseName
newExercise.workouts.setByAddingObject(workoutName)
return newExercise
}
}
这是我的锻炼实体:
import Foundation
import CoreData
class Workouts: NSManagedObject {
@NSManaged var workoutName: String
@NSManaged var sessions: NSSet
@NSManaged var exercises: NSSet
class func createWorkoutInManagedObjectContext(moc: NSManagedObjectContext, workoutName: String) -> Workouts {
let newWorkout = NSEntityDescription.insertNewObjectForEntityForName("Workouts", inManagedObjectContext: moc) as Workouts
newWorkout.workoutName = workoutName
return newWorkout
}
}
谢谢,这听起来不错。我会添加到我的createExerciseInManagedObjectContext函数或saveNewItem函数? – Sean 2015-02-24 23:09:55
嗯,只是在saveNewItem函数中试过这个,我得到'Workouts'没有名为'addExerciseObject'的成员? – Sean 2015-02-24 23:13:59
这取决于关系名称。只要看看Workout.swift。 – Mundi 2015-02-24 23:26:21