gpt4 book ai didi

Swift - 为相关的 CoreData 实体赋值

转载 作者:行者123 更新时间:2023-11-28 05:30:39 25 4
gpt4 key购买 nike

我正在构建一个具有两个 CoreData 实体的应用程序 - 锻炼和锻炼。两者之间是多对多的关系。

该应用程序是一对基本的 tableViewController,允许您将锻炼 (workoutName) 添加到 Workouts 实体,然后在下一个 tableViewController 中将锻炼添加到该 Workout。我正在苦苦挣扎的是如何将每个练习分配回它在 CoreData 中起源的锻炼。本质上,当我向 Exercises 实体添加 newExercise(使用 exerciseName 变量)时,我要做的是在 Workouts 实体中设置 workoutsName 值。

我将 workoutName 作为 var workout 通过 Workouts tableViewController 的 segue 传递给 Exercise tableViewController。

我也有多对多关系,并在 NSManagedObjects 文件中设置为 NSSet,但不知道如何使用它们。

这是练习设置的 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.
}

}

此外,这是在我的练习类中定义的函数 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
}

我可以将所选锻炼的字符串 (workoutName) 传递到此函数中,但不知道如何通过与锻炼实体的锻炼关系来设置它。

这是我的练习实体:

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
}

}

最佳答案

如果正确设置模型,两个实体将通过关系相互引用。您将实体添加到另一个实体,而不是它的名称(这是一个属性)。

当您创建 NSManagedObject 子类时,Core Data 应该会自动生成访问器。有了这些,向锻炼中添加新的(或现有的)锻炼就非常简单了:

workout.addExercisesObject(newExercise)

这假设您的关系称为练习

因此,将实际锻炼对象而不是其名称传递给函数实际上更可取。不要忘记保存。

编辑:
为了让它工作,你有两个选择。

或者让 Xcode 在 Objective-C 中生成 NSManagedObject 子类并自动配置桥接头。然后您可以毫不费力地获得访问器。

或者您必须自己实现它们。例如:

@objc(Exercise)
class Exercise: NSManagedObject {

@NSManaged var workouts: NSSet

func addWorkoutsObject(value: Workout!) {
var mutableWorkouts = self.workouts.mutableCopy() as! NSMutableSet
mutableWorkouts.addObject(value)
self.workouts = mutableWorkouts as NSSet
}
}

请注意,我没有添加键值编码调用,因此除非您添加它们,否则 KVO 将无法工作。

关于Swift - 为相关的 CoreData 实体赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28702369/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com