Swift CoreData在UITableViews之间传递选定的行值

时间:2015-02-21 21:13:12

标签: ios uitableview swift core-data segue

我是Swift和编码的新手,仅仅一个月左右,我正在尝试构建一些简单的UItableViews来设置一些CoreData属性。

我的CoreData实体的结构是锻炼实体和锻炼实体之间的多对多关系。 (我会张贴一些图片,但我没有足够高的代表!)

我想要实现的是一个简单的设置菜单,用户可以通过在顶部使用带有navigationController的tableViews创建一个Workout,然后在该Workout中创建一系列练习(就像iOS设置菜单一样)

目前我已经开始工作了,你可以添加一些锻炼,然后你可以去Excercises tableView添加一些练习。但是我无法做两件事:

1)当用户添加练习时,如何将其分配给他们从上一个tableView中选择的正确锻炼,我该如何确保?

2)我怎样才能确保练习表只显示他们选择的锻炼练习?

我已经围绕这个主题做了很多阅读,并认为答案与从锻炼到练习的segue有关(通过使用委托将exerciseName传递给Exercises tableView?然后使用NSPredicate来限制选择锻炼显示的锻炼?

我不是百分百肯定,但是非常感谢任何帮助!

以下是从锻炼到锻炼的segue代码:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "excerciseMaster" {
        let ExcerciseMasterTableViewController = segue.destinationViewController as UIViewController
        let indexPath = tableView.indexPathForSelectedRow()!
        let workout = workouts[indexPath.row]
        let destinationTitle = workout.workoutName
        ExcerciseMasterTableViewController.title = destinationTitle
    }
}

这是我的Exercises tableViewController的代码:

import UIKit
import CoreData

class ExcerciseMasterTableViewController: UITableViewController {

// Create an empty array of Excercises
var excercises = [Excercises]()

// 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 {
    }

    fetchExcercises()
}

func fetchExcercises() {
    let fetchRequest = NSFetchRequest(entityName: "Excercises")

    // Create a sort descriptor object that sorts on the "excerciseName"
    // property of the Core Data object
    let sortDescriptor = NSSortDescriptor(key: "excerciseName", 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? [Excercises] {
        excercises = 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 excercises, so return the count
    return excercises.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCellWithIdentifier("Excercise Cell", forIndexPath: indexPath) as UITableViewCell

    // Get the Excercises for this index
    let excercise = excercises[indexPath.row]

    // Set the title of the cell to be the title of the excercise
    cell.textLabel!.text = excercise.excerciseName
    cell.detailTextLabel!.text = "\(excercise.sets)x\(excercise.reps)"
    cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
    return cell
}

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if(editingStyle == .Delete ) {
        // Find the Excercise object the user is trying to delete
        let excerciseToDelete = excercises[indexPath.row]

        // Delete it from the managedObjectContext
        managedObjectContext?.deleteObject(excerciseToDelete)

        // Refresh the table view to indicate that it's deleted
        self.fetchExcercises()

        // 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 excercise = excercises[indexPath.row]
}

let addExcerciseAlertViewTag = 0
let addExcerciseTextAlertViewTag = 1


@IBAction func addExcerciseButton(sender: AnyObject) {
    var namePrompt = UIAlertController(title: "Add Excercise",
        message: "Enter Name",
        preferredStyle: .Alert)

    var excerciseNameTextField: UITextField?
    namePrompt.addTextFieldWithConfigurationHandler {
        (textField) -> Void in
        excerciseNameTextField = textField
        textField.placeholder = "Title"
    }

    namePrompt.addAction(UIAlertAction(title: "Ok",
        style: .Default,
        handler: { (action) -> Void in
            if let textField = excerciseNameTextField {
                self.saveNewItem(textField.text, workoutName: "Workout A")
            }
    }))

    self.presentViewController(namePrompt, animated: true, completion: nil)
}

func saveNewItem(excerciseName : String, workoutName: String) {
    // Create the new excercise item
    var newExcercise = Excercises.createExcerciseInManagedObjectContext(self.managedObjectContext!, name: excerciseName)
    println(excerciseName)
    println(workoutName)

    // Update the array containing the table view row data
    self.fetchExcercises()

    // Animate in the new row
    // Use Swift's find() function to figure out the index of the newExcercise
    // after it's been added and sorted in our Excercises array
    if let newExcerciseIndex = find(excercises, newExcercise) {
        // Create an NSIndexPath from the newExcerciseIndex
        let newExcerciseIndexPath = NSIndexPath(forRow: newExcerciseIndex, inSection: 0)
        // Animate in the insertion of this row
        tableView.insertRowsAtIndexPaths([ newExcerciseIndexPath ], 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 == "excerciseSettings" {
        let ExcerciseSettingsDetailViewController = segue.destinationViewController as UIViewController
        let indexPath = tableView.indexPathForSelectedRow()!
        let excercise = excercises[indexPath.row]
        let destinationTitle = excercise.excerciseName
        ExcerciseSettingsDetailViewController.title = destinationTitle
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

1 个答案:

答案 0 :(得分:0)

1.塞古很接近。您的ExcerciseMasterTableViewController没有名为workout的属性。你需要添加

var workout:Workout!

到你的ExcerciseMasterTableViewController。

你的seque看起来应该更像这个

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "excerciseMaster" {
    let desitnationController = segue.destinationViewController as ExcerciseMasterTableViewController
    let indexPath = tableView.indexPathForSelectedRow()!
    let workout = workouts[indexPath.row]
    destinationController.workout = workout
    let destinationTitle = workout.workoutName
    desitnationController.title = destinationTitle // Usually you would put this in the viewDidLoad method of the destinationController
}

}

然后在你的ExcerciseMasterTableViewController中添加练习时,只需设置他们的训练属性

workout.exercises = exercises // See note in #2
  1. 为了确保只显示正确的练习,在viewDidLoad中将练习数组设置为workout.exercises。请注意,workout.exercises应该是一个NSSet,因此您需要将您的集转换为数组,或者让练习的类型为NSSet而不是数组。