core data predicate format in string swift4 - swift

I am using core data. For fetching data I want to give predicate as string. I have stored predicate in string attribute in database.
Below is code I am trying
let request = NSFetchRequest<Tasks>(entityName: "Tasks")
print("Query is .." ,item.query!)
request.predicate = NSPredicate(format: item.myqueryString!)
myqueryString is string attribute in core data where I am storing predicate as -
projectName == "spot"
But on fetching data it is giving error "NSInvalidArgumentException', reason: 'keypath spot not found in entity".
Anyone can explain what is wrong? Thanks in advance

Related

How to query CloudKit by lastModifiedUserRecordID?

Based on Apple documentation, lastModifiedUserRecordID, is a system field that's auto generated on iCloud.
I want to fetch records from the public iCloud database that where last modified by me.
I set "modifiedBy" as Queryable on the CloudKit Dashboard and added this predicate:
let userId = CKRecord.Reference(recordID: userCKRecordID, action: .none)
lastModifiedPred = NSPredicate(format: "lastModifiedUserRecordID = %#", userId)
And it returns no results. If I remove this predicate, it returns 1 result and I can see in the dashboard that the last modified by record id (recordName) matches with the user recordName I'm sending it.
Oddly enough, using "creatorUserRecordID" and passing the same value as above does return proper results but I need lastModifiedBy.
EDIT: Per the suggestions I tried to use the actual userCKRecord.recordName as a string and sending this predicate to CloudKit.
lastModifiedPred = NSPredicate(format: "lastModifiedUserRecordID = %#", userCKRecord.recordName)
and received this error:
"Field \'___modifiedBy\' has a value type of REFERENCE and cannot be
queried using filter value type STRING"
As I mentioned above, I can query creatorUserRecordID just fine using the original predicate at the top (using CKRecord.ID), but it just doesn't work for lastModifiedUserRecordID.
Since you want to fetch records that were last modified by you, you have to get first your UserRecordID. This is done by calling
fetchUserRecordID(completionHandler: { (myUserRecordID, error) in
… // see below
}
see the docs. This way, you get your user myUserRecordID.
With this, you can setup your query predicate:
let lastModifiedPred = NSPredicate(format: "lastModifiedUserRecordID = %#", myUserRecordID)
and execute your query.
You are using NSPredicate to compare a string literal. Where userId is not a string literal. Use this.
lastModifiedPred = NSPredicate(format: "lastModifiedUserRecordID = %d", INT-VALUE-OF-userId)
Based on apple documentation on https://developer.apple.com/documentation/cloudkit/ckrecord/id
CKRecord.ID -> class ID : NSObject
A record ID object consists of a name string and a zone ID. The name
string is an ASCII string not exceeding 255 characters in length.
comparing an object and string won't give you the result, try to cast the CKRecord.ID as String maybe help

Filter to NSFetchRequest

hi i'm not really understanding how the fetch filter works can anyone help me please? So i currently have this as my fetchall function which displays all of my items within my entity
im having trouble of filtering only one attribute which is a boolean. I want it to only display attributes that are true.
thankyou!
func fetchAllItems(){
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "AllItems")
do{
let result = try managedObjectContext.fetch(request)
beastList = result as! [AllItems]
} catch { print("\(error)")
}
}
Code:
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "AllItems")
request.predicate = NSPredicate(format: "something = %#", argumentArray: [true])
Note: Replace something with your boolean field name
Better way to create request
let request : NSFetchRequest<AllItems> = AllItems.fetchRequest()
Naming convention:
It is better to name your entity in singular form, so that each row in your entity could be in singular form.
AllItems seems very generic, if you are storing cars, the entity name could be Car. The variable that stores the result of the fetch request could be cars.
Reference:
https://developer.apple.com/documentation/foundation/nspredicate
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html

coredata fetch records where the relation is not existing

I have an entity in swift with an optional relation towards another entity. Now I want to select those records without a relation towards the other entity.
I tried with a predicate (format: "relation = %#", nill) but this does not work.
how to fetch records without the relation filled?
Try this:
let fetchRequest: NSFetchRequest = YourEntity.fetchRequest()
let predicate = NSPredicate(format: "%K == nil", #keyPath(YourEntity.yourOptionalAttribute))
fetchRequest.predicate = predicate
// the rest of your code to perform the fetch goes here
#K is for keyPath. You just want to search where the keyPath is nil.

CloudKit Server Rejected Request: Unknown field recordName

I am doing a CKQuery like this in Swift 4:
CKQuery(recordType: package.recordType, predicate:
NSPredicate(format: "NOT (recordName IN %#)", package.recordNames as CVarArg))
...and I'm getting this CKError:
CKError(_nsError: CKError 0x60000024dce0: "Server Rejected Request" (15/2000); server message = "Unknown field 'recordName'"; uuid = BCD7C8DA-04B0-4422-8A24-F6479D234706; container ID = "...")
Is there a special key to use when querying against the recordName?
After digging some more, I discovered that you cannot query by the recordName directly, but you can query by the recordID. So instead of comparing an array of strings, you have to build an array of CKRecordIDs and query like this:
//- 1 - Build an array of CKRecordIDs
package.recordIDs = [CKRecordID(recordName: "..."), CKRecordID(recordName: "...")]
//- 2 - Set the predicate to use the `recordID` key
let pred = NSPredicate(format: "NOT (recordID IN %#)", package.recordIDs as CVarArg)
//- 3 - Set the query and drop your mic
CKQuery(recordType: package.recordType, predicate: pred)
I hope that helps someone else.

How can I get core data entity by it's objectID?

I have a list objects from coredata and then I get objectId from one of those objects:
let fetchedId = poi.objectID.URIRepresentation()
Now I need to get entity for this specific objectID.
And I tried something like:
let entityDescription = NSEntityDescription.entityForName("Person", inManagedObjectContext: managedObjectContext!);
let request = NSFetchRequest();
request.entity = entityDescription;
let predicate = NSPredicate(format: "objectID = %i", fetchedId);
request.predicate = predicate;
var error: NSError?;
var objects = managedObjectContext?.executeFetchRequest(request,
error: &error)
But I get error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath objectID not found in entity <NSSQLEntity Person id=4>'
You can't query arbitrary properties of the NSManagedObject with a predicate for a NSFetchRequest. This will only work for attributes that are defined in your entity.
NSManagedObjectContext has two ways to retrieve an object with an NSManagedObjectID. The first one raises an exception if the object does not exist in the context:
managedObjectContext.objectWithID(objectID)
The second will fail by returning nil:
var error: NSError?
if let object = managedObjectContext.existingObjectWithID(objectID, error: &error) {
// do something with it
}
else {
println("Can't find object \(error)")
}
If you have a URI instead of a NSManagedObjectID you have to turn it into a NSManagedObjectID first. The persistentStoreCoordinator is used for this:
let objectID = managedObjectContext.persistentStoreCoordinator!.managedObjectIDForURIRepresentation(uri)
What you get is not the object ID, but the URI. The object ID is a part of the URI. You can ask the persistent store coordinator for the object ID with
- managedObjectIDForURIRepresentation:. Having the object ID you can get the object from the context using for example -objectWithID:. But please look to the documentation, of this methods for some reasons.