Adrian
Adrian

Reputation: 16715

Implementing a UISearchController in Swift Core Data Project

I'm presently taking an iOS development course. As part of an assignment, I'm tasked with creating a UISearchController in a note tracking project using Core Data in Swift.

Every example I've found is in Objective-C or is filtering a static array. Apple's "sample" code, updated in December 2014 doesn't compile in Xcode 6.3.

To add a UISearchController, I've got 3 primary tasks to do:

1) Create a view controller to present search results. I'm using a TableViewController.

2) Create a UISearchController, and pass it my search results view controller.

What's "stumping" me is now to get a hold of the objects in the managedObjectsContext. Prior to attempting to add a UISearchController, my app works fine. I can add, edit, and delete items. I'm using the "canned" Core Data code in Xcode 6.3 with the stack in AppDelegate.

class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate

    var searchController: UISearchController? = nil

func addSearchBar() {
    var resultsController = SearchResultsTableViewController()
    resultsController.notes = // stumped what to call the notes. Trying to call an array from the Notes class below
    resultsController.delegate = self

    searchController = UISearchController(searchResultsController: resultsController)
    searchController!.searchResultsUpdater = resultsController
    searchController!.searchBar.frame = CGRect(
        x: searchController!.searchBar.frame.origin.x,
        y: searchController!.searchBar.frame.origin.y, width: searchController!.searchBar.frame.size.width, height: 44.0)

    tableView.tableHeaderView = searchController!.searchBar
    self.definesPresentationContext = true
}

3) The UISearchController will notify its searchResultsUpdater (a class that conforms to UISearchResultsUpdating) when the search text changes. I'm using my search results view controller implement this protocol so I can update the filtered results.

Below is my Note: NSManagedObject class:

import Foundation
import CoreData

class Note: NSManagedObject {

@NSManaged var dateCreated: NSDate
@NSManaged var dateEdited: NSDate
@NSManaged var noteTitle: String
@NSManaged var noteBody: String

// TODO: adding this to make it easier to handle names
class func notes() -> NSArray {
    let whereMyNotesAreStored = // Need syntax for where my MyManagedObjectContext is located
    let dataArray = NSArray(contentsOfFile: whereMyNotesAreStored!)

    var notesArray = NSMutableArray()

    for dictionary in dataArray {
        var note = Note()
        note.noteTitle = dictionary["noteTitle"] as! String
        note.noteBody = dictionary["noteBody"] as! String
        note.dateCreated = dictionary["dateCreated"] as! String
        note.dateEdited = dictionary["dateEdited"] as! String

        notesArray.addObject(note)
    }

    return NSArray(array: notesArray as! [AnyObject])
}

}

Upvotes: 1

Views: 1121

Answers (1)

pbasdf
pbasdf

Reputation: 21536

There are two approaches to setting the context:

Calling back to the App Delegate:, like this

    let appDelegate : AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    let context = appDelegate.managedObjectContext!

or passing the context forward from the App Delegate to the Master View Controller, which then passes it on to any subsequent view controllers, etc. Each view controller will need a property defined for the context; when a new VC is instantiated, the context is set before the VC is presented/pushed, eg:

    class CustomViewController : UIViewController {
        var managedObjectContext : NSManagedObjectContext
        ...

and, when loading a new view controller,

    let newVC = CustomViewController()
    newVC.managedObjectContext = self.managedObjectContext
    ...

To access the objects, use either a NSFetchRequest or NSFetchedResultsController to create an array of results, which you can then pass to the resultsController. eg. for a fetch request:

    let fetch = NSFetchRequest(entityName: "Notes")
    var error : NSError? = nil
    let fetchedResults = managedObjectContext?.executeFetchRequest(fetch, error: &error)

(Your notes() function is on the wrong track - you would not use NSArray(contentsOfFile:) to access CoreData objects. Also, you must use the designated initialiser for NSManagedObject subclasses: so not var note = Notes() but var note = Notes(entity: NSEntityDescription, insertIntoManagedObjectContext: NSManagedObjectContext?)

Upvotes: 2

Related Questions