I am somewhat stuck trying to write a helper function for querying my CoreData store.
For simple things (like string values etc) the following syntax works well:
let predicate = NSPredicate(format:"myProperty == (someString)")
However, it breaks if I try to say something like "self in (arrayOfIDs)"
.
Here is a small reproducible example which breaks:
let ids = [1,2,3]
let predicate = NSPredicate(format:"self in (ids)")
Running this code fails with libc++abi: terminating due to uncaught exception of type NSException
. Clearly, NSPredicate cannot be constructed in such a way.
I have figured out that the issue can be resolved if I actually use CVarArg
s like so:
let ids = [1,2,3]
let predicate = NSPredicate(format:"self in %@", args: ids)
However, as I try to employ this in a function where I am going to pass predicate, I would like to avoid passing format and CVarArgs.
So my next logical assumption is that I could construct a String using String(format:String, args: any CVarArg...)
and pass this as a predicate format without additional arguments.
Surprisingly, this breaks as well:
let ids = [1,2,3]
let predicate = NSPredicate(format:String(format:"self in %@", args: ids))
Does anyone have any idea how this could be resolved?
For context, this is the function which I am trying to write:
static func fetch<T:FetchDeclaringManagedObject>(_ request:NSFetchRequest<T>, predicate:String?, context:NSManagedObjectContext = defaultContext, sortDescriptors:[NSSortDescriptor]? = nil) -> [T] {
let request = T.fetchRequest()
if let p = predicate {
request.predicate = NSPredicate(format: p)
}
// REST OF CODE
}
It would be super convenient if I did not have to rewrite it to specify both format and CVarArgs 🙂
5
That function feels like over-generalization to me, but if you’re set on having it, what I’d do is
- Write a second function with almost the same arguments as that function, only with the
predicate
argument replaced with an argument that contains an array of IDs. - In that second function,
- Create the predicate
- Then, call the function you have above.
It’s a little different when you call it, but since you apparently already have an array of IDs, this is the easy way to get things working.