rickGrimes88
rickGrimes88

Reputation: 1

pass core data between views swift

I'm currently working on an inventory app that will hold information for two entities. The first entity holds two attributes "site name" and "site address". second entity holds "itemName" "itemQuantity" and "item picture". I'm able to save the data to core data. I'm having issues with fetching the data right now. Does any one know how to pass data between the view controllers.

I'm uploading the site view controller, detail view controller, and my new item view controller.

class SiteTableViewController: UIViewController {


    var managedContext : NSManagedObjectContext = CoreDataHelper.sharedInstance.myContext
    var sites : [Site]? = [Site]()

    //variable to hold selected site
    var selectedSite : Site?

    let myCellIdentifier = "cell"



    @IBOutlet weak var tableView: UITableView!


    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        // Do any additional setup after loading the view.
        sites = [Site]()
        reloadData()

        automaticallyAdjustsScrollViewInsets = false


        //let barButtonItem = UIBarButtonItem(barButtonSystemItem: .Compose, target: self, action: "addSite:")
        //self.navigationItem.leftBarButtonItems = [barButtonItem]
    }




    //load new data into table 
    func reloadData() {

        let fetchRequest = NSFetchRequest(entityName: "Site")
        let sortDescriptor = NSSortDescriptor(key: "siteName", ascending: true)

        fetchRequest.sortDescriptors = [sortDescriptor]

        do {
            sites = try self.managedContext.executeFetchRequest(fetchRequest) as! [Site]
            tableView.reloadData()

        } catch {

            print("Error fetching objects")

        }
        tableView.reloadData()


    }



    override func viewWillAppear(animated: Bool) {

       reloadData()

    }



}

extension SiteTableViewController: UITableViewDataSource, UITableViewDelegate {

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier(myCellIdentifier, forIndexPath: indexPath)

        let site = sites![indexPath.row]

        cell.textLabel?.text = site.valueForKey("siteName") as? String
        cell.detailTextLabel?.text = site.valueForKey("siteAddress") as? String

        return cell
    }

    func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {

        return true
    }

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

        if editingStyle == .Delete {

        let logItemToDelete = sites![indexPath.row]
        sites?.removeAtIndex(indexPath.row)
        managedContext.deleteObject(logItemToDelete)

            do {

                try managedContext.save()

            } catch {

                print("Could not save or delete object")
            }

             tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        }

    }





    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return sites!.count 

    }

//    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//        
//        selectedSite = sites![indexPath.row]
//        
//    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == "detailSegue" {

            var nextVC = segue.destinationViewController as! DetailTableViewController
            var selectedItem : Site = sites![self.tableView.indexPathForSelectedRow!.row] as Site

            fetchSite = selectedItem.valueForKey("siteName") as? NSManagedObject
            nextVC.valueToPass = selectedItem.siteName!

        }

    }

}

here is my detail view controller

import UIKit
import CoreData

public var fetchSite : NSManagedObject?

class DetailTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var holdSiteData: NSMutableArray = NSMutableArray()
    var managedContext : NSManagedObjectContext = CoreDataHelper.sharedInstance.myContext


    @IBOutlet weak var tableView: UITableView!


    var sites : [Site]!


    //string to hold fetchResults controll



    //open string to hold siteName
    var valueToPass = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationItem.title = "\(valueToPass)" 

        // Do any additional setup after loading the view.

        tableView.delegate = self
        tableView.dataSource = self

        automaticallyAdjustsScrollViewInsets = false
        tableView.estimatedRowHeight = 75.0
        tableView.rowHeight = UITableViewAutomaticDimension

        retrieveItemRelationship()

    }

    override func viewWillAppear(animated: Bool) {

        retrieveItemRelationship()
    }



    func retrieveItemRelationship() {

       // fetchSite.setValue(NSSet(keyCommands), forKey: "test")
        let fetchRequest = NSFetchRequest(entityName: "SiteItem") 
        let sortDescriptors = NSSortDescriptor(key: "itemName", ascending: true)
        fetchRequest.sortDescriptors = [sortDescriptors]

        do {

            let result = try fetchSite?.managedObjectContext?.executeRequest(fetchRequest)


        } catch let error as NSError {

            print(error)
        }


    }





    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell

    //    let cellInfo = fetchedResultsController.objectAtIndexPath(indexPath) as! SiteInfo



        cell.cellName?.text = "Test"




        return cell
    }



    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return holdSiteData.count


    }


}

this is my last view to save the data to. I figured i need to pass the data here then associate the two entities so that I can save it correctly. For instance, for site name "Staples Center". I need to pull this over to the final view controller then save the information to this object.

import UIKit
import CoreData

class ItemNewViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    //var managedObjectContext : NSManagedObjectContext!

    var managedContext : NSManagedObjectContext = CoreDataHelper.sharedInstance.myContext


    //categories array for picker view
    var categories = ["Building Materials", "Electrical", "Cleaning Products",
        "Tools & Hardware", "Plumbing", "Paint", "Appliances", "Other"]

    //textFields

    @IBOutlet weak var itemNameTextField: UITextField!
    @IBOutlet weak var quantityTextField: UITextField!



    @IBOutlet weak var imageView: UIImageView!


    //Label properties
    @IBOutlet weak var newItemLabel: UILabel!
    @IBOutlet weak var quantityLabel: UILabel!
    @IBOutlet weak var categoryLabel: UILabel!


    //pickerLabel
    @IBOutlet weak var pickerListIcon: UIPickerView!



    //clicker property label and textlabel for number
    @IBOutlet weak var increaseNumberClicker: UIStepper!
    @IBOutlet weak var numberFieldClicker: UITextField!




    override func viewDidLoad() {
        super.viewDidLoad()

        //label property customize view code
        newItemLabel.layer.masksToBounds = true
        newItemLabel.layer.borderWidth = 2.0
        newItemLabel.layer.borderColor = UIColor.whiteColor().CGColor
        newItemLabel.layer.cornerRadius = 6

        //label property customize view code
        quantityLabel.layer.masksToBounds = true
        quantityLabel.layer.borderWidth = 2.0
        quantityLabel.layer.borderColor = UIColor.whiteColor().CGColor
        quantityLabel.layer.cornerRadius = 6

        //lable property customize view code
        categoryLabel.layer.masksToBounds = true
        categoryLabel.layer.borderWidth = 3.0
        categoryLabel.layer.borderColor = UIColor.whiteColor().CGColor
        categoryLabel.layer.cornerRadius = 6

        //label picker customize view
        pickerListIcon.layer.masksToBounds = true
        pickerListIcon.layer.borderWidth = 3.0
        pickerListIcon.layer.borderColor = UIColor.whiteColor().CGColor
        pickerListIcon.layer.cornerRadius = 6
        pickerListIcon.layer.backgroundColor = UIColor.blackColor().CGColor



        self.pickerListIcon.dataSource = self
        self.pickerListIcon.delegate = self


        numberFieldClicker.enabled = false


        //UIStepper value
        increaseNumberClicker.wraps = true
        increaseNumberClicker.autorepeat = true
        increaseNumberClicker.layer.masksToBounds = true
        increaseNumberClicker.layer.borderWidth = 3.0
        increaseNumberClicker.layer.borderColor = UIColor.whiteColor().CGColor
        increaseNumberClicker.layer.cornerRadius = 6
        increaseNumberClicker.layer.backgroundColor = UIColor.blackColor().CGColor



        //below code declares a variable that inherits from UITapGesture
        //this allows the image view to be an action
        //*Make sure you enable user interaction in storyBoard very IMPORTANT!
        let imageTapRecognizer = UITapGestureRecognizer(target: self, action: "enableImage")

        self.imageView.addGestureRecognizer(imageTapRecognizer)
    }


    // below function allows the camera view to be accessible
    func enableImage(){

        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {

            let cameraView = UIImagePickerController()
            cameraView.sourceType = UIImagePickerControllerSourceType.Camera
            cameraView.delegate = self

            self.presentViewController(cameraView, animated: true, completion: nil)

        }

    }

    func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {

        self.imageView.image = image

        picker.dismissViewControllerAnimated(true, completion: nil)
    }



    //function used to increase UIStepper. increment by integers of one
    @IBAction func clickerIncreaser(sender: UIStepper) {



        numberFieldClicker.text = Int(sender.value).description


    }


    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {

        return 1
    }


    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

        return categories.count
    }



    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

        return categories[row]
    }


    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {

        //passing the categorories array into the new constant myCategoriesArray
        let myCategoriesArray = categories[row]

        let myTextColor = NSAttributedString(string: myCategoriesArray, attributes: [NSForegroundColorAttributeName: UIColor.whiteColor()])

        return myTextColor
    }


    //save data to core data


    @IBAction func saveButton(sender: AnyObject) {



       if (itemNameTextField.text?.isEmpty)! {

        let displayAlertController = UIAlertController(title: "Form Incomplete", message: "Please provide item with a name", preferredStyle: .Alert)


        let okButton : UIAlertAction = UIAlertAction(title: "OK", style: .Default, handler: nil)

        displayAlertController.addAction(okButton)

        self.presentViewController(displayAlertController, animated: true, completion: nil)

       } else {


        //declare site object and object
        let siteInfoEntity = NSEntityDescription.entityForName("SiteItem", inManagedObjectContext: self.managedContext)

       //declare item and item object

        let siteObject = SiteItem(entity: siteInfoEntity!, insertIntoManagedObjectContext: self.managedContext)

        //convert String to Integer 
        let quantityNumber: Int? = Int(quantityTextField.text!)

        siteObject.setValue(itemNameTextField.text?.capitalizedString, forKey: "itemName")
        siteObject.setValue(quantityNumber, forKey: "itemQnty")

        fetchSite?.setValue(NSSet(object: siteObject), forKey: "reverseItems")

        self.managedContext.saveOrLogError()


        self.navigationController?.popViewControllerAnimated(true)

     }

    }


}

Once again if someone can point me in the right direction for saving my relationships to core data and retrieving these relationships would be great. Still new to core data so need all the help i can get!

Thank you

Upvotes: 0

Views: 1257

Answers (1)

Mundi
Mundi

Reputation: 80273

Your detail controller can have a property Site. In prepareForSegue you pass the selected Site object to the detail controller.

Both the site list and the list of items should be backed by NSFetchedResultsController, not in-memory arrays.

Upvotes: 0

Related Questions