NSPreidcate Use string to filter Core Data table

In my iOS app I have 2 tableViewControllers. In the first one will the user select a vehicle the name of the vehicle is then stored in a string, and passed to te next tableViewController. In the second tableViewController I want to display all Core Data entries that has the saved string as value for the attribute fordon.

I have figured out that I probably should use NSPredicate for this, but I don not know how to write the correct code.

At the moment my code looks like this:

´fetchRequest.predicate = NSPredicate(format: "fordon == %s", registreringsnummer)

The result is that it displays nothing in the second tableViewController, unless I replace the first "=" with "!" then it displays every entry.

Can you please give me some help in order to write correct code.

You should review the NSPredicate Programming Guide,most likely the solution will be in the format specifier section. Perhaps changing %s to %@. If fordon is a string attribute then that should work. See the link provided and let me know if that solves your issue by clicking the link below. If it doesn't please update the thread.

I took a look at your link, and tried a couple of format specs. I have tried most of them before. I have been stuck with this problem since March.

I uploaded my project to GitHub, if you want to take a look at the whole project.

I did take a look but the project is empty. At a minimum please define your core data model and update the project so that it does show some of the things you've tried. If you do that then I can help you get past the hurdle with an actual code example that makes sense in the context of your project.


If you need a better start try out the Simple Core Data Relationships sample project in Xcode (it's still called TaggedLocations). You will be able to see how two core data objects are modeled and how to add the related objects to each other in code. To find and open the sample, just go to your Help tab and open the Documentation ~ from there just search for the words I mentioned above.

Are you sure the project is epty? I am new to GitHub, so I am not sure. I synced it again, please check out.

It's not completely empty but there's only been one commit 9 months ago. I don't see any view controllers. You probably need to Push (not sync).

Tank you. The project should now be updated.

OK, I looked at the project and didn't find the text fordon or registreringsnummer in the project.


Looking at your data model there is one Entity with five properties. (a date, several floats and a string). For the predicate to match you want the type of the attribite and the type of the value you're comparing it to to be the same (usually) and you want the predicate string to match that type.


func predicateWithValue(value: Float) -> NSFetchRequest {

let predicate = NSPredicate(format: "attributeName == %f", value)

return prdicate

}


Be aware that comparing floating point values for eqality is problematic and this may be the source of your problems. You may have better results using integers or strings for these values.

I think the reason you didn´t find the fordon or registreringsnummer is because thoose belongs to the Core Data model Fordon. T reason for that is that I save the entries from the first tableVC (fordonTableViewController) in Fordon. Then I want to use Fordon.registreringsnummer to filter out thoose entries in the second Data model (Model) that has the same value for the attribute "fordon", and then display thoose entries in the tableVC tankningarTableViewController.


It is a bit confusing with almost the same name for different attribute in differnt locations, I know.


I am aware of the Floats and I think I will make the double instead. 'Thoose are just supposed to do a division befored stored (and if the user typed it correctly, never changed). The Floats should not be used in any comparison.

After reviewing the project I think the best thing to do is to quickly review the options available. In prepareforSegue you may want to do one of two things:

  • Assign the value(s) of registreringsnummer to a variable on your second tableview controller (not an IBOutlet, just a var) ; then build the fetchrequest using that variable after viewDidLoad
  • Create the fetch and pass the results to an array variable on your second tableview controller (not an IBOutlet, just a var); then use the array values after viewDidLoad

In your uploaded project I did not find an attribute "fordon" on your entity, so assigning anything to a non-existent attribute will not work. Either update your model with a valid attribute OR test the query process using an existing attribute like kronor, liter, or literpris as a test to confirm that the basic functionality works.

The test would be to simply choose one of the methods above and within either your second view controller run the fetch request on the value provided (as described above).

OR

You can build a fetch request with a predicate and pass the array of results to the second controller. (sample code provided below)

Important ~ Put a break point in your code so that you can validate the variable, predicate, and fetch results before they are passed between the first tableview controller and the second tableview controller.

To make the values available on the second tableviewcontroller just add the variables.

class secondTableViewController:UITableViewController {
var registreringsnummer: Float = 0.0 //I did not see this value on your model
...
}

//Note - I would handle a string search very differently since it does not have good

// performance using equality operators

// Check this link for other predicate operators

//You must create a variable to hold the objects you will use in the second tableview controller

class secondTableViewController:UITableViewController {
var fetchResults = [Tankningslista]()
..
}


To send the values from the first tableviewcontroller you need to setup a data reference to hold the outgoing objects.

class tankningarTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {
...
  var fetchedResultsController: NSFetchedResultsController? = nil
  let context = (UIApplication.sharedApplication().delegate asAppDelegate).managedObjectContext!
...


In your tankningarTableViewController you will want to prepare the data and assign it to the variable on your secondTableViewController

override func prepareForSegue {
...
if let secondTableViewController = segue.destinationViewController as? SecondTableViewControllerClassName {
    secondTableViewController.fetchedResults = self.fetchTankningslistaObjects (2.0)
...
}


This function will perform the fetch and return the objects that you can then assign to your second tableview controller (in the prepareForSegue)

// typical example of returning an array of objects from a fetch with a predicate argument
// you could change the argument to different values/types as needed
// check that the predicate and argument values are correct by adding a breakpoint into the function
func fetchTankningslistaObjects (argument:Float)->[Tankningslista] {
    //get your fetch results prepared to send to the second tableviewcontroller as an array
    var fetchRequest:NSFetchRequest = NSFetchRequest(entityName: "Tankningslista")
    fetchRequest.fetchLimit = 25
    let sortDescriptorsArray = [NSSortDescriptor(key: "date", ascending: false)]
    let aPredicate = NSPredicate(format: "kronor = %@", argument) 
    // if kronor is an attribute and argument is a valid float your predicate should work when applied to a Modeled entity with the same attribute name and argument type, change the attribute name and matching argument type as needed
    fetchRequest.sortDescriptors = sortDescriptorsArray
    fetchRequest.predicate = aPredicate
    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.context sectionNameKeyPath: nil, cacheName: nil)
    fetchedResultsController.delegate = self
        do
        {
            try self.fetchedResultsController!.performFetch()
        } catch let e as NSError {
            /
            fatalError(e.localizedDescription)
        }
    return self.frc!.fetchedObjects as? [Tankningslista]
}


This is written off the top of my head. You will probably need to find and fix small optionality errors. I noticed that your existing code is Swift 1.2.

Important - Please update to the latest version of Xcode if possible and convert to Swift 2.0.

Hopefully this resolves your issue and gives a good idea of how to move the data between the tableview controllers. You still need to setup the tableview controllers to populate correctly using the array of objects. If this helps please click the link below so that others can find this solution. Otherwise update the thread.

NSPreidcate Use string to filter Core Data table
 
 
Q