{"id":1312,"date":"2014-10-15T11:10:27","date_gmt":"2014-10-15T17:10:27","guid":{"rendered":"http:\/\/jamesonquave.com\/blog\/?p=1312"},"modified":"2015-02-16T16:14:17","modified_gmt":"2015-02-16T22:14:17","slug":"core-data-in-swift-tutorial-part-2","status":"publish","type":"post","link":"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/","title":{"rendered":"Core Data in Swift Tutorial (Part 2)"},"content":{"rendered":"<p><strong>This post compatible with Xcode 6.3, Updated on February 16, 2015<\/strong><\/p>\n<p>This is part two of a tutorial series covering the usage of Core Data in Swift to write iOS apps with persistence. If you haven&#8217;t read part one yet, <a href=\"http:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-1\/\">read that first<\/a>.<\/p>\n<p>If you really want to get your feet wet,  <a href=\"http:\/\/jamesonquave.com\/swiftebook\">my Swift book which is now available for pre-order<\/a> with early access.<\/p>\n<p><strong>Creating more records<\/strong><\/p>\n<p>First off, if we&#8217;re going to do anything more interesting than just showing a single record pop up in an alert, we&#8217;ll need to generate some more records to play with. Let&#8217;s open up our LogItem.swift file and add a helper function for adding new records.<\/p>\n<p>Basically, we want to be able to simply call a method on the LogItem class, pass in some parameters, and get a new LogItem back.<\/p>\n<p>For example, when we&#8217;re done the actual function call might look like this:<\/p>\n<pre class=\"brush: js;\">\r\nlet newItem = LogItem.createInManagedObjectContext(managedObjectContext, \"Item Title\", \"Item text\")\r\n<\/pre>\n<p>The LogItem class is not tied to any specific NSManagedObjectContext, so we want to make sure we aren&#8217;t storing the reference to the managed object context anywhere in the model, it needs to be passed in when we want to create an object like this.<\/p>\n<p>Okay so let&#8217;s implement the method in LogItem.swift:<\/p>\n<pre class=\"brush: js; highlight: [6,7,8,9,10,11,12];\" title=\"LogItem.swift\">\r\nclass LogItem: NSManagedObject {\r\n\r\n    @NSManaged var itemText: String\r\n    @NSManaged var title: String\r\n\r\n    class func createInManagedObjectContext(moc: NSManagedObjectContext, title: String, text: String) -&gt; LogItem {\r\n        let newItem = NSEntityDescription.insertNewObjectForEntityForName(\"LogItem\", inManagedObjectContext: moc) as! LogItem\r\n        newItem.title = title\r\n        newItem.itemText = text\r\n        \r\n        return newItem\r\n    }\r\n    \r\n}\r\n<\/pre>\n<p>The first line is the function definition. It&#8217;s a class function called <i>createInManagedObjectContext<\/i>, which takes an object of type <b>NSManagedObjectContext<\/b> as the argument <i>moc<\/i>, a <b>String<\/b> called <i>title<\/i>, and a <b>String<\/b> called <i>text<\/i>. The function returns a <b>LogItem<\/b> object that&#8217;s been inserted in to the specified managed object context.<\/p>\n<p>Then it executes nearly identical code as before to create a new LogItem object, except now it&#8217;s using the arguments passed in to the function to set up the new LogItem object.<\/p>\n<p>We can replace our original code in ViewController.swift now to just use the new method. Let&#8217;s add a bunch of new items&#8230;<\/p>\n<pre class=\"brush: js\" title=\"ViewController.swift\">\r\noverride func viewDidLoad() {\r\n    super.viewDidLoad()\r\n    \/\/ Do any additional setup after loading the view, typically from a nib.\r\n    \r\n    \/\/ Use optional binding to confirm the managedObjectContext\r\n    if let moc = self.managedObjectContext {\r\n        \r\n        \/\/ Create some dummy data to work with\r\n        var items = [\r\n            (\"Best Animal\", \"Dog\"),\r\n            (\"Best Language\",\"Swift\"),\r\n            (\"Worst Animal\",\"Cthulu\"),\r\n            (\"Worst Language\",\"LOLCODE\")\r\n        ]\r\n        \r\n        \/\/ Loop through, creating items\r\n        for (itemTitle, itemText) in items {\r\n            \/\/ Create an individual item\r\n            LogItem.createInManagedObjectContext(moc,\r\n                title: itemTitle, text: itemText)\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>To keep the code simple, we&#8217;re using some shortcuts in order to seed our data. What you&#8217;re seeing when I&#8217;m setting <strong>items<\/strong> is an array (using square brackets []), then each element is a tuple of two String values, <strong>[(String, String)]<\/strong>.<\/p>\n<p>Next, I&#8217;m decomposing them back in to two variables, itemTitle and itemText for each of the tuples in the array.<\/p>\n<p>Finally, I call the createInManagedObjectContext method, which we created earlier, passing in the new itemTitle and itemText.<\/p>\n<p><i><br \/>\nIf you already know how to set up a UITableView programmatically and want to skip ahead to the Core Data stuff, <a href=\"#part25\">click here<\/a>.<br \/>\n<\/i><\/p>\n<p>Now that we have a couple of records, let&#8217;s remove <strong>presentItemInfo<\/strong> and instead opt for a table view here. We&#8217;ll add this all right under viewDidLoad and programmatically create the UITableView. In my <a href=\"http:\/\/jamesonquave.com\/blog\/developing-ios-apps-using-swift-tutorial\/\">iTunes tutorial<\/a> we do this using storyboards. If you are more interested in working with storyboards I recommend taking a pit stop there to read about how to get that set up.<\/p>\n<p>We&#8217;ll set up the tableView by adding a <strong>logTableView<\/strong> to the ViewController class, and set it all up in viewDidLoad()<\/p>\n<pre class=\"brush: js;\">\r\n\/\/ Create the table view as soon as this class loads\r\nvar logTableView = UITableView(frame: CGRectZero, style: .Plain)\r\n\r\noverride func viewDidLoad() {\r\n    super.viewDidLoad()\r\n    \/\/ Do any additional setup after loading the view, typically from a nib.\r\n    \r\n    \/\/ Use optional binding to confirm the managedObjectContext\r\n    if let moc = self.managedObjectContext {\r\n        \r\n        \/\/ Create some dummy data to work with\r\n        var items = [\r\n            (\"Best Animal\", \"Dog\"),\r\n            (\"Best Language\",\"Swift\"),\r\n            (\"Worst Animal\",\"Cthulu\"),\r\n            (\"Worst Language\",\"LOLCODE\")\r\n        ]\r\n        \r\n        \/\/ Loop through, creating items\r\n        for (itemTitle, itemText) in items {\r\n            \/\/ Create an individual item\r\n            LogItem.createInManagedObjectContext(moc,\r\n                title: itemTitle, text: itemText)\r\n        }\r\n        \r\n        \r\n        \/\/ Now that the view loaded, we have a frame for the view, which will be (0,0,screen width, screen height)\r\n        \/\/ This is a good size for the table view as well, so let's use that\r\n        \/\/ The only adjust we'll make is to move it down by 20 pixels, and reduce the size by 20 pixels\r\n        \/\/ in order to account for the status bar\r\n        \r\n        \/\/ Store the full frame in a temporary variable\r\n        var viewFrame = self.view.frame\r\n        \r\n        \/\/ Adjust it down by 20 points\r\n        viewFrame.origin.y += 20\r\n        \r\n        \/\/ Reduce the total height by 20 points\r\n        viewFrame.size.height -= 20\r\n        \r\n        \/\/ Set the logTableview's frame to equal our temporary variable with the full size of the view\r\n        \/\/ adjusted to account for the status bar height\r\n        logTableView.frame = viewFrame\r\n        \r\n        \/\/ Add the table view to this view controller's view\r\n        self.view.addSubview(logTableView)\r\n        \r\n        \/\/ Here, we tell the table view that we intend to use a cell we're going to call \"LogCell\"\r\n        \/\/ This will be associated with the standard UITableViewCell class for now\r\n        logTableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: \"LogCell\")\r\n        \r\n        \/\/ This tells the table view that it should get it's data from this class, ViewController\r\n        logTableView.dataSource = self\r\n        \r\n    }\r\n}\r\n<\/pre>\n<p>Since we set the dataSource to be our ViewController class, we also need to adhere to the UITableViewDataSource protocol, so add that to the ViewController&#8217;s class definition:<\/p>\n<pre class=\"brush: js;\">\r\nclass ViewController: UIViewController, UITableViewDataSource {\r\n<\/pre>\n<p>&#8230;and add the actual dataSource methods&#8230;<\/p>\n<pre class=\"brush: js;\">\r\n\/\/ MARK: UITableViewDataSource\r\nfunc tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\r\n    return 5\r\n}\r\n\r\nfunc tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {\r\n    let cell = tableView.dequeueReusableCellWithIdentifier(\"LogCell\") as! UITableViewCell\r\n    cell.textLabel?.text = \"\\(indexPath.row)\"\r\n    return cell\r\n}\r\n<\/pre>\n<p>Still with me? Hope so&#8230; if not here&#8217;s the full ViewController.swift code up until this point. Note that we also removed the viewDidAppear function since we were only using that for testing out some things earlier.<\/p>\n<pre class=\"brush: js\">\r\nimport UIKit\r\nimport CoreData\r\n\r\nclass ViewController: UIViewController, UITableViewDataSource {\r\n    \r\n    \/\/ Retreive the managedObjectContext from AppDelegate\r\n    let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext\r\n\r\n    \/\/ Create the table view as soon as this class loads\r\n    var logTableView = UITableView(frame: CGRectZero, style: .Plain)\r\n\r\n    override func viewDidLoad() {\r\n        super.viewDidLoad()\r\n        \/\/ Do any additional setup after loading the view, typically from a nib.\r\n        \r\n        \/\/ Use optional binding to confirm the managedObjectContext\r\n        if let moc = self.managedObjectContext {\r\n            \r\n            \/\/ Create some dummy data to work with\r\n            var items = [\r\n                (\"Best Animal\", \"Dog\"),\r\n                (\"Best Language\",\"Swift\"),\r\n                (\"Worst Animal\",\"Cthulu\"),\r\n                (\"Worst Language\",\"LOLCODE\")\r\n            ]\r\n            \r\n            \/\/ Loop through, creating items\r\n            for (itemTitle, itemText) in items {\r\n                \/\/ Create an individual item\r\n                LogItem.createInManagedObjectContext(moc,\r\n                    title: itemTitle, text: itemText)\r\n            }\r\n            \r\n            \r\n            \/\/ Now that the view loaded, we have a frame for the view, which will be (0,0,screen width, screen height)\r\n            \/\/ This is a good size for the table view as well, so let's use that\r\n            \/\/ The only adjust we'll make is to move it down by 20 pixels, and reduce the size by 20 pixels\r\n            \/\/ in order to account for the status bar\r\n            \r\n            \/\/ Store the full frame in a temporary variable\r\n            var viewFrame = self.view.frame\r\n            \r\n            \/\/ Adjust it down by 20 points\r\n            viewFrame.origin.y += 20\r\n            \r\n            \/\/ Reduce the total height by 20 points\r\n            viewFrame.size.height -= 20\r\n            \r\n            \/\/ Set the logTableview's frame to equal our temporary variable with the full size of the view\r\n            \/\/ adjusted to account for the status bar height\r\n            logTableView.frame = viewFrame\r\n            \r\n            \/\/ Add the table view to this view controller's view\r\n            self.view.addSubview(logTableView)\r\n            \r\n            \/\/ Here, we tell the table view that we intend to use a cell we're going to call \"LogCell\"\r\n            \/\/ This will be associated with the standard UITableViewCell class for now\r\n            logTableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: \"LogCell\")\r\n            \r\n            \/\/ This tells the table view that it should get it's data from this class, ViewController\r\n            logTableView.dataSource = self\r\n            \r\n        }\r\n    }\r\n    \r\n    \/\/ MARK: UITableViewDataSource\r\n    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\r\n        return 5\r\n    }\r\n    \r\n    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {\r\n        let cell = tableView.dequeueReusableCellWithIdentifier(\"LogCell\") as! UITableViewCell\r\n        cell.textLabel?.text = \"\\(indexPath.row)\"\r\n        return cell\r\n    }\r\n\r\n    override func didReceiveMemoryWarning() {\r\n        super.didReceiveMemoryWarning()\r\n        \/\/ Dispose of any resources that can be recreated.\r\n    }\r\n\r\n}\r\n<\/pre>\n<p>This will give us a numbered list of rows if we run the app. This just confirms the table view is set up correctly.<\/p>\n<p><i>If you ever get an error that says something like, <b>The model used to open the store is incompatible with the one used to create the store<\/b><br \/>\nThis means that the model Core Data thinks it&#8217;s working with doesn&#8217;t quite match what&#8217;s been stored in the database. Resolving this with a live app means migrating between versions of your model. But for the purpose of learning and doing the initial development, usually the quickest way to just keep moving is to delete the app from the simulator; wiping out the data, and therefore resolving the conflict.<\/i><\/p>\n<p><a href=\"http:\/\/jamesonquave.com\/blog\/wp-content\/uploads\/tableView.png\"><img decoding=\"async\" src=\"http:\/\/jamesonquave.com\/blog\/wp-content\/uploads\/tableView.png\"><\/a><\/p>\n<p>Now that we have this all set up and ready to go, we can start working on getting our log data showing up in the table view.<\/p>\n<p><i>Please note that at this point in the tutorial, I&#8217;m intentionally avoiding the NSFetchedResultsController class. I&#8217;m doing this because I believe it will make more sense from the Core Data perspective the first time around if you see it done the old fashioned way. After this tutorial is over, I encourage you to look over the class and see how you might use it to implement some of these things instead. I think it is important to first learn how to implement a core data backed table view without using the helper class. The helper class is not applicable in all situations, and learning it first would be doing yourself a disservice. You&#8217;ll find it doesn&#8217;t work for all use cases (not even close), and in it&#8217;s magic it hides some of what&#8217;s going on.<\/i><\/p>\n<p>First off, let&#8217;s fetch all the results from Core Data in viewDidLoad(), and store them in an array of LogItem&#8217;s, <strong>logItems<\/strong>.<\/p>\n<p>First we&#8217;ll add the variable to the ViewController class:<\/p>\n<pre class=\"brush: js;\">\r\n\/\/ Create an empty array of LogItem's\r\nvar logItems = [LogItem]()\r\n<\/pre>\n<p>Next, we&#8217;ll populate it from viewDidLoad(), inside of a function called fetchLog().<\/p>\n<pre class=\"brush: js;\">\r\noverride func viewDidLoad() {\r\n    ...\r\n    fetchLog()\r\n}\r\n\r\nfunc fetchLog() {\r\n    let fetchRequest = NSFetchRequest(entityName: \"LogItem\")\r\n    if let fetchResults = managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [LogItem] {\r\n        logItems = fetchResults\r\n    }\r\n}\r\n<\/pre>\n<p>Now we can modify the tableView dataSource methods to refer to this array instead of hard-coding values.<\/p>\n<pre class=\"brush: js;\">\r\n\/\/ MARK: UITableViewDataSource\r\nfunc tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\r\n    \/\/ How many rows are there in this section?\r\n    \/\/ There's only 1 section, and it has a number of rows\r\n    \/\/ equal to the number of logItems, so return the count\r\n    return logItems.count\r\n}\r\n\r\nfunc tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {\r\n    let cell = tableView.dequeueReusableCellWithIdentifier(\"LogCell\") as! UITableViewCell\r\n    \r\n    \/\/ Get the LogItem for this index\r\n    let logItem = logItems[indexPath.row]\r\n    \r\n    \/\/ Set the title of the cell to be the title of the logItem\r\n    cell.textLabel?.text = logItem.title\r\n    return cell\r\n}\r\n<\/pre>\n<p>This should set us up to see the items listed in the table view, but we want to show the text of an item when it&#8217;s clicked. So we need to set the table view to use this view controller as it&#8217;s delegate, so we can receive the callback method, <strong>didSelectRowAtIndexPath<\/strong>.<\/p>\n<p>Similar to before, add the <strong>UITableViewDelegate<\/strong> protocol to the class&#8230;<\/p>\n<pre class=\"brush: js;\">\r\nclass ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {\r\n<\/pre>\n<p>And set the delegate to be self, you can do this right under where you set the dataSource in viewDidLoad&#8230;<\/p>\n<pre class=\"brush: js;\">\r\n\/\/ This tells the table view that it should get it's data from this class, ViewController\r\nlogTableView.dataSource = self\r\nlogTableView.delegate = self\r\n<\/pre>\n<p>Finally we can implement the method, knowing the Table View will call it when a cell is clicked&#8230;<\/p>\n<pre class=\"brush: js;\">\r\n\/\/ MARK: UITableViewDelegate\r\nfunc tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {\r\n    let logItem = logItems[indexPath.row]\r\n    println(logItem.itemText)\r\n}\r\n<\/pre>\n<p>This will set us up so that when the button is clicked, a message will show in the console (in the Xcode window) showing the itemText for the clicked item.<\/p>\n<div id=\"part25\" name=\"part25\">&nbsp; <\/div>\n<p>The purpose of this tutorial is not really to explain how to set up a table view manually, but it&#8217;s sort of necessary in order to get a good look at the data. For this reason, I&#8217;m providing the source code up until this point in the tutorial <a href=\"https:\/\/github.com\/jquave\/Core-Data-In-Swift-Tutorial\/tree\/Part2.5\">here<\/a>. Feel free to simply check this out and work from this code base, from here we&#8217;ll be talking more about the Core Data side of things.<br \/>\n<a href=\"https:\/\/github.com\/jquave\/Core-Data-In-Swift-Tutorial\/tree\/Part1.5\">https:\/\/github.com\/jquave\/Core-Data-In-Swift-Tutorial\/tree\/Part1.5<\/a><\/p>\n<p>You may see something kind of like this now, except with different data:<\/p>\n<p><a href=\"http:\/\/jamesonquave.com\/blog\/wp-content\/uploads\/TableList1.png\"><img decoding=\"async\" src=\"http:\/\/jamesonquave.com\/blog\/wp-content\/uploads\/TableList1.png\" \/><\/a><\/p>\n<p>Your ordering may be different every time you run your app, this is because it contains no sorting when it performs the fetch request. In some data stores you might get this data back in the same order as it was inserted, but with Core Data it ends up being fairly random. Let&#8217;s change this by adding a sort to the fetch request.<\/p>\n<pre class=\"brush: js;\">\r\nfunc fetchLog() {\r\n    let fetchRequest = NSFetchRequest(entityName: \"LogItem\")\r\n    \r\n    \/\/ Create a sort descriptor object that sorts on the \"title\"\r\n    \/\/ property of the Core Data object\r\n    let sortDescriptor = NSSortDescriptor(key: \"title\", ascending: true)\r\n    \r\n    \/\/ Set the list of sort descriptors in the fetch request,\r\n    \/\/ so it includes the sort descriptor\r\n    fetchRequest.sortDescriptors = [sortDescriptor]\r\n    \r\n    if let fetchResults = managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [LogItem] {\r\n        logItems = fetchResults\r\n    }\r\n}\r\n<\/pre>\n<p>Now the fetch request has it&#8217;s sortDescriptors property set. Note that this is an array, which is why we need the brackets around the single <strong>sortDescriptor<\/strong> we created using the title key. Running the app you should now see the sorted (alphabetically) list of items, much better. Note your data is expected to be different.<\/p>\n<p><a href=\"http:\/\/jamesonquave.com\/blog\/wp-content\/uploads\/sorted.png\"><img decoding=\"async\" src=\"http:\/\/jamesonquave.com\/blog\/wp-content\/uploads\/sorted.png\" \/><\/a><\/p>\n<p>Let&#8217;s also look at filtering out certain elements. First, let&#8217;s just try and only get the item named &#8220;Best Language&#8221;. We&#8217;ll create an NSPredicate that uses a string to represent the requirement that any object must fulfill in order to pass through the query.<\/p>\n<pre class=\"brush: js;highlight: [12,13,14,15,16,17];\">\r\nfunc fetchLog() {\r\n    let fetchRequest = NSFetchRequest(entityName: \"LogItem\")\r\n    \r\n    \/\/ Create a sort descriptor object that sorts on the \"title\"\r\n    \/\/ property of the Core Data object\r\n    let sortDescriptor = NSSortDescriptor(key: \"title\", ascending: true)\r\n    \r\n    \/\/ Set the list of sort descriptors in the fetch request,\r\n    \/\/ so it includes the sort descriptor\r\n    fetchRequest.sortDescriptors = [sortDescriptor]\r\n    \r\n    \/\/ Create a new predicate that filters out any object that\r\n    \/\/ doesn't have a title of \"Best Language\" exactly.\r\n    let predicate = NSPredicate(format: \"title == %@\", \"Best Language\")\r\n    \r\n    \/\/ Set the predicate on the fetch request\r\n    fetchRequest.predicate = predicate\r\n    \r\n    if let fetchResults = managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [LogItem] {\r\n        logItems = fetchResults\r\n    }\r\n}\r\n<\/pre>\n<p>If you haven&#8217;t seen the format syntax yet, or haven&#8217;t seen it in a while, it&#8217;s simple enough to say that any time you see format as a named parameter, it comes from the Objective-C methods &#8220;predicateWithFormat&#8221;, or &#8220;stringWithFormat&#8221;, and so on. This replaces any instances of the %@ symbol with an object&#8217;s description (the value of a string, or an otherwise useful representation of other types of objects). For primitive types such as an Int, you&#8217;ll want to instead opt for %i, %f for Float, and so on.<\/p>\n<p>So when you see<br \/>\n<strong>(format: &#8220;title == %@&#8221;, &#8220;Best Language&#8221;)<\/strong><\/p>\n<p>What the compiler sees is something like this:<br \/>\n<strong>(&#8220;title == &#8216;Best Language'&#8221;)<\/strong><\/p>\n<p>So we&#8217;re just specifying we want title to equal that exact string.<\/p>\n<p>Running the app now we should see just one item.<\/p>\n<p>We could also do a string comparison using the contains keyword, if we look for the substring &#8220;Worst&#8221; we&#8217;ll only get the items that contain that string&#8230;<\/p>\n<pre class=\"brush: js\">\r\n\/\/ Search for only items using the substring \"Worst\"\r\nlet predicate = NSPredicate(format: \"title contains %@\", \"Worst\")\r\n\r\n\/\/ Set the predicate on the fetch request\r\nfetchRequest.predicate = predicate\r\n<\/pre>\n<p>What if we wanted to combine the two though? We want both items containing the string &#8220;Worst&#8221; and any one with a title &#8220;Best Language&#8221;?<\/p>\n<p>First, let&#8217;s create the two separate predicates:<\/p>\n<pre class=\"brush: js;\">\r\n\/\/ Create a new predicate that filters out any object that\r\n\/\/ doesn't have a title of \"Best Language\" exactly.\r\nlet firstPredicate = NSPredicate(format: \"title == %@\", \"Best Language\")\r\n\r\n\/\/ Search for only items using the substring \"Worst\"\r\nlet thPredicate = NSPredicate(format: \"title contains %@\", \"Worst\")\r\n<\/pre>\n<p>Then combine them using the NSCompoundPredicate constructor:<\/p>\n<pre class=\"brush: js;\">\r\n\/\/ Combine the two predicates above in to one compound predicate\r\nlet predicate = NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [firstPredicate, thPredicate])\r\n\r\n\/\/ Set the predicate on the fetch request\r\nfetchRequest.predicate = predicate\r\n<\/pre>\n<p>Since we want both cases of the &#8220;Best Language&#8221; and any item containing &#8220;Worst&#8221;, we use a compound predicate type of <strong>NSCompoundPredicateType.OrPredicateType<\/strong><\/p>\n<p>All this is just a confusing way of saying, &#8220;give me any items where the firstPredicate <strong>or<\/strong> the thPredicate is true.&#8221;<\/p>\n<p>What we did here is quite powerful in practice. We can use string comparison as predicates, and filter\/order large lists of data through Core Data. The Core Data API will then connect to the backing store (SQLite) and produce an efficient query to quickly retrieve the needed information. This is a very common pattern in iOS development, and understanding it is very important. So, if you got stuck on this tutorial or have any questions, don&#8217;t hesitate to ask for help on the <a href=\"http:\/\/jamesonquave.com\/forums\">forums<\/a>.<\/p>\n<p>This concludes Part 2 for now, in the next section we&#8217;ll move in to a more applicable scenario by adding a way for user&#8217;s to create log items, edit, save, and delete them.<\/p>\n<p><a href=\"https:\/\/github.com\/jquave\/Core-Data-In-Swift-Tutorial\/tree\/Part2\">The complete source code to this section &raquo;<\/a><\/p>\n<div class=\"tut-toc\">\n<a href=\"http:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-1\/\"  class=\"tutorial-part-button\">Part 1<\/a><br \/>\n<a href=\"http:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/\" class=\"tutorial-part-button current\">Part 2<\/a><br \/>\n<a href=\"http:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-3\/\" class=\"tutorial-part-button\">Part 3<\/a><br \/>\n<a href=\"http:\/\/jamesonquave.com\/blog\/core-data-migrations-swift-tutorial\/\" class=\"tutorial-part-button\">Part 4<\/a>\n<\/div>\n<p>If you&#8217;re reading this scratching your head, or just want a deeper dive in to Core Data, be sure to look at <a href=\"http:\/\/jamesonquave.com\/swiftebook\">my Swift book, which is now available for early access<\/a>. And don&#8217;t forget to <a href=\"http:\/\/eepurl.com\/sDFL9\">subscribe to get updates<\/a> on this tutorial series via e-mail.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post compatible with Xcode 6.3, Updated on February 16, 2015 This is part two of a tutorial series covering the usage of Core Data in Swift to write iOS apps with persistence. If you haven&#8217;t read part one yet, read that first. If you really want to get your feet wet, my Swift book&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_links_to":"","_links_to_target":""},"categories":[25,10,32],"tags":[61,15,33,36],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v19.13 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Core Data in Swift Tutorial (Part 2) - Jameson Quave<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Core Data in Swift Tutorial (Part 2) - Jameson Quave\" \/>\n<meta property=\"og:description\" content=\"This post compatible with Xcode 6.3, Updated on February 16, 2015 This is part two of a tutorial series covering the usage of Core Data in Swift to write iOS apps with persistence. If you haven&#8217;t read part one yet, read that first. If you really want to get your feet wet, my Swift book...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Jameson Quave\" \/>\n<meta property=\"article:published_time\" content=\"2014-10-15T17:10:27+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2015-02-16T22:14:17+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/jamesonquave.com\/blog\/wp-content\/uploads\/tableView.png\" \/>\n<meta name=\"author\" content=\"Jameson Quave\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jameson Quave\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/\",\"url\":\"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/\",\"name\":\"Core Data in Swift Tutorial (Part 2) - Jameson Quave\",\"isPartOf\":{\"@id\":\"https:\/\/jamesonquave.com\/blog\/#website\"},\"datePublished\":\"2014-10-15T17:10:27+00:00\",\"dateModified\":\"2015-02-16T22:14:17+00:00\",\"author\":{\"@id\":\"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/db6184f355c7f4e3b876d0f228c2fcfc\"},\"breadcrumb\":{\"@id\":\"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/jamesonquave.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Core Data in Swift Tutorial (Part 2)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/#website\",\"url\":\"https:\/\/jamesonquave.com\/blog\/\",\"name\":\"Jameson Quave\",\"description\":\"Using computer technology to educate, and improve lives.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/jamesonquave.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/db6184f355c7f4e3b876d0f228c2fcfc\",\"name\":\"Jameson Quave\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d9786c83345117d560bbeab0e1f26814?s=96&d=retro&r=pg\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d9786c83345117d560bbeab0e1f26814?s=96&d=retro&r=pg\",\"caption\":\"Jameson Quave\"},\"sameAs\":[\"http:\/\/jamesonquave.com\"],\"url\":\"https:\/\/jamesonquave.com\/blog\/author\/jquave\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Core Data in Swift Tutorial (Part 2) - Jameson Quave","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/","og_locale":"en_US","og_type":"article","og_title":"Core Data in Swift Tutorial (Part 2) - Jameson Quave","og_description":"This post compatible with Xcode 6.3, Updated on February 16, 2015 This is part two of a tutorial series covering the usage of Core Data in Swift to write iOS apps with persistence. If you haven&#8217;t read part one yet, read that first. If you really want to get your feet wet, my Swift book...","og_url":"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/","og_site_name":"Jameson Quave","article_published_time":"2014-10-15T17:10:27+00:00","article_modified_time":"2015-02-16T22:14:17+00:00","og_image":[{"url":"http:\/\/jamesonquave.com\/blog\/wp-content\/uploads\/tableView.png"}],"author":"Jameson Quave","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Jameson Quave","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/","url":"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/","name":"Core Data in Swift Tutorial (Part 2) - Jameson Quave","isPartOf":{"@id":"https:\/\/jamesonquave.com\/blog\/#website"},"datePublished":"2014-10-15T17:10:27+00:00","dateModified":"2015-02-16T22:14:17+00:00","author":{"@id":"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/db6184f355c7f4e3b876d0f228c2fcfc"},"breadcrumb":{"@id":"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/jamesonquave.com\/blog\/core-data-in-swift-tutorial-part-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/jamesonquave.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Core Data in Swift Tutorial (Part 2)"}]},{"@type":"WebSite","@id":"https:\/\/jamesonquave.com\/blog\/#website","url":"https:\/\/jamesonquave.com\/blog\/","name":"Jameson Quave","description":"Using computer technology to educate, and improve lives.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jamesonquave.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/db6184f355c7f4e3b876d0f228c2fcfc","name":"Jameson Quave","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d9786c83345117d560bbeab0e1f26814?s=96&d=retro&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d9786c83345117d560bbeab0e1f26814?s=96&d=retro&r=pg","caption":"Jameson Quave"},"sameAs":["http:\/\/jamesonquave.com"],"url":"https:\/\/jamesonquave.com\/blog\/author\/jquave\/"}]}},"_links":{"self":[{"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/posts\/1312"}],"collection":[{"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/comments?post=1312"}],"version-history":[{"count":52,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/posts\/1312\/revisions"}],"predecessor-version":[{"id":1653,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/posts\/1312\/revisions\/1653"}],"wp:attachment":[{"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/media?parent=1312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/categories?post=1312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/tags?post=1312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}