Realm object predicate search is invalid - swift

Using Realm DB in a swift application. I'm trying to filter the results with a predicate as follows:
class func fetchUsersFromDB(usersId: [String]) -> [User]{
var users = [User]()
let realm = Realm()
let predicate = NSPredicate(format: "objectId IN %#", argumentArray: usersId)
var allUsers = realm.objects(User).filter(predicate)
users = Array(allUsers)
return users
}
But this won't compile. I get this error:
Terminating app due to uncaught exception 'Invalid value', reason: 'IN clause requires an array of items'
Any ideas what I'm doing wrong?

Remove the argumentArray: label, as with it you're calling the wrong initializer for NSPredicate:
let predicate = NSPredicate(format: "objectId IN %#", usersId)

As of Swift 3, just use Array(usersId) instead of usersId.

Related

SWiftUI - Check if object exist in core data and return a boolean

I'm trying to use a NSPredicate to filter items in core data if a value exist or not but i want to return a boolean so I can add it to core data if the result is false and remove it if it's true.
func addItem(item: String) {
let newItem = CoffeeFavorite(context: managedObjectContext)
newItem.title = item
saveFavorites()
}
private func deleteFavorite(title: String) throws {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "CoffeeFavorit
request.predicate = NSPredicate(format: "title == %#", title)
try managedObjectContext.execute(NSBatchDeleteRequest(fetchRequest: request))
}
I'm using these 2 function to add and delete items from core data but I need another one to check if the item exists so I can use one instead of the other with an if statement.
I guess I need to match a predicate that returns a boolean but I don't know how to do it

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.

Optional Types With Parse and Swift

if var findPublisher:PFQuery = PFUser.query(){
findPublisher.whereKey("objectId", equalTo:quote.objectForKey("publisher").objectId)//error here
}
I am getting an error Value of any optional type 'Any Object'? not unwrapped. I don't know what i have done incorrectly. I am a beginner so please bear with me:)
This is really a place where you would give each quote a pointer to a user object, and then you could just get the publisher of the quote without an extra query. But if you want to do it this way, you would do:
let query = PFUser.query()!
query.whereKey("objectId", equalTo: (quote["publisher"] as! String)) // You can unwrap it as long as you are sure that quote is not nil, and the publisher is set.
query.getFirstObjectInBackgroundWithBlock({ (user: PFObject?, error: NSError?) in
// check for errors and use the object
})
This way of doing it also creates Parse security issues, as anyone with your app's ID and key can get a full user list.
let findPublisher = PFUser.query()!
findPublisher.whereKey("objectId", equalTo: (quote["publisher"] as! String))
findPublisher.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]?, error:NSError?)->Void in
if error == nil{
let user:PFUser = (objects as NSArray).lastObject as! PFUser//error here
cell.publisherLabel.text = user.username
}
}
I end up getting an error that says that AnyObject is not convertible to NSArray?

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.

Can I apply multiple predicates to an NSFetchRequest? Would it be better to manually parse my results?

Ok I have a basic iPad app that asks for 5 search/filter criteria from the user. Based on this data, I need to go to my core data db, and pull out any managed objects that fit that criteria. It seems like I need to apply more than one predicate to the same request, is that possible? Or could I just write a really long fancy predicate? With multiple requirements? How should I approach that?
Would it be a good idea to just grab all the entities through the fetch request, and then loop through each array and grab any objects that I find that fit my search criteria?
Please advise!
Yes it's possible. You're looking for compound predicates and here's an example with AND predicates:
NSPredicate *compoundPredicate
= [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray of Predicates]];
You can also use notPredicateWithSubpredicates and orPredicateWithSubpredicates depending on your needs.
Link to documentation https://developer.apple.com/documentation/foundation/nscompoundpredicate
Swift 4
let fetchRequest: NSFetchRequest<YourModelEntityName> = YourModelEntityName.fetchRequest()
let fooValue = "foo"
let barValue = "bar"
let firstAttributePredicate = NSPredicate(format: "firstAttribute = %#", fooValue as CVarArg)
let secondAttributePredicate = NSPredicate(format: "secondAttribute = %#", barValue as CVarArg)
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [firstAttributePredicate, secondAttributePredicate])
more information about different types of NSCompoundPredicate constructors can be found here
yes you can apply like this below
do {
let request = UserDeatils.fetchRequest() as NSFetchRequest<UserDeatils>
let firstAttributePredicate = NSPredicate(format: "userName = %#", userNameTextField.text!)
let secondAttributePredicate = NSPredicate(format: "password = %#", passwordTF.text!)
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [firstAttributePredicate, secondAttributePredicate])
self.userDataArray = try context.fetch(request)
print("Fetching Data", userDataArray)
if userDataArray.isEmpty {
print("no user found")
} else {
print("Login Succesfully")
}
} catch {
print("Wrong Username and password")
}