1

I'm trying to fetch all my items from Core Data that doesn't have "X" in its allergens attribute.

func doesNotContain(attribute: String = "allergens", text: String) {
    let request: NSFetchRequest<Dinner> = Dinner.fetchRequest()
    let predicate = NSPredicate(format:"NOT \(attribute) CONTAINS %@", text)
    request.predicate = predicate
    do { items = try context.fetch(request) }
    catch let error { print("Error: \(error)") }
}

For some reason this crashes with "EXC_BAD_ACCESS"

But it works perfectly fine when I'm trying to fetch with a predicate using:

func containsSearchWithNSPredicate(attribute: String, text: String) {
    let request: NSFetchRequest<Dinner> = Dinner.fetchRequest()
    let predicate = NSPredicate(format: "\(attribute) CONTAINS[cd] %@", text)
    request.predicate = predicate
    do { items = try context.fetch(request) }
    catch let error { print("Error: \(error)") }
}

The attribute here is set to "name" when the function is called, and it's set to "allergens" in the first example

I've made sure that the attribute "allergens" is not nil, and I've also tried using %d instead of %@. The allergens attribute is an array, and that's why I'm using NOT CONTAINS

  • @matt No, but NSPredicate should work with NOT CONTAINS aswell as CONTAINS, Shouldn't it? The first example is NOT CONTAINS – Henrik Knudsen Feb 24 '21 at 20:11
  • 1
    Does it work with extra parentheses, as in https://stackoverflow.com/a/12535373/1187415 ? – Martin R Feb 24 '21 at 20:15
  • Exactly my point. You are saying `NOT \(attribute)`. – matt Feb 24 '21 at 20:16
  • 2
    It the `allergens` attribute is an array, then the predicate will not work (as part of a fetch) anyway. – pbasdf Feb 24 '21 at 20:41
  • @matt I though NOT X CONTAINS was valid, and X NOT CONTAINS wasn't valid syntax? – Henrik Knudsen Feb 24 '21 at 20:52
  • @pbasdf Yes, the allergens attribute is an array. Is there any way to make the predicate work then, or will i have to make a work around? – Henrik Knudsen Feb 24 '21 at 20:52
  • @MartinR No, sadly it doesn't work with extra parentheses – Henrik Knudsen Feb 24 '21 at 20:57
  • 1
    `NSPredicate(format: "\(attribute) CONTAINS[cd] %@", text)` should be `NSPredicate(format: "%K CONTAINS[cd] %@", attribute, text)`, it's better. – Larme Feb 24 '21 at 21:11
  • If it's an array then you want `NOT (... IN ...)` – matt Feb 24 '21 at 21:13
  • Does this answer your question? [NSPredicate query for not containing a specific string](https://stackoverflow.com/questions/12534629/nspredicate-query-for-not-containing-a-specific-string) – Larme Feb 24 '21 at 21:14
  • @Larme, No it doesn't sadly. I think the problem has to do with the attribute being an array, like pbasdf stated. – Henrik Knudsen Feb 24 '21 at 21:34
  • 1
    If `attribute` is an Array, shouldn't if be `"ANY attributes CONTAINS %@"` instead to be working? It's no CoreData, but that's why your behavior is strange: https://pastebin.com/p1iFFb0q you should use `ANY`, except if you put some stranges values on `attribute`. – Larme Feb 24 '21 at 22:02
  • @Larme "let predicate = NSPredicate(format:"NOT (ANY attributes CONTAINS %@)", text)" as suggested in your pastebin didn't work sadly. – Henrik Knudsen Feb 25 '21 at 00:14

1 Answers1

1

Turns out that NSPredicate doesn't work with attributes marked as "Transformable" with a custom class of [String].

I made it work by instead of having an array, I made it to a String, separating each individual allergen with ";" to make it possible to divide into substrings later.

allergen example:

dinner.allergens = "Gluten;Dairy"

The NSPredicate:

let predicate = NSPredicate(format:"NOT (%K CONTAINS[cd] %@)",attribute, text)

The fetch request will now get all entities that does not have an allergen attribute containing text