use subquery in Cloudkit - ios

Anyone knows how to use subquery in CloudKit? Here is my trying code:
// stringArray is String list in Cloudkit
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SUBQUERY(stringArray, $fS, ANY $fS = %#).#count != 0", targetString];
CKQuery *query = [[CKQuery alloc] initWithRecordType:#"TestRecord" predicate:predicate];
[publicDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
NSLog(#"%#", results);
}];
But caught CKException and showed failed message Expected key-path in comparison expression: SUBQUERY(stringArray, $fS, ANY $fS = "targetString").#count != 0
Any idea or something wrong?

Have a look at the documentation about NSPredicates for CloudKit.
https://developer.apple.com/library/ios/documentation/CloudKit/Reference/CKQuery_class/index.html#//apple_ref/swift/cl/CKQuery
As you can see it only allows a subset of what you can do for the full NSPredicate class. Subqueries and aggregates (like the .#count) are not allowed.

Related

How to Query in Ascending using Parse

Currently even if I do orderByAscending it never does it by ascending.
What is the issue that I do not see? I am using Parse
PFQuery *foodList = [PFQuery queryWithClassName:#"Food"];
[foodList whereKey:#"date" greaterThanOrEqualTo:minimumDate];
[foodList whereKey:#"date" lessThan:maximumDate];
[foodList orderByAscending:#"expiration_date"];
[foodList findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
}];
Example
food_name expiration_date
Apple 1/2/15
Banana 1/2/15
Pear 1/3/15
Kiwi 1/1/15
Output
The outputs would be very random.
I am assuming that the list is not being sorted while it is querying. I am unsure how to solve this problem though.
I use the NSSortDescriptor variant to do sorting with the Parse SDK and haven't had any issues with that (also filtering on multiple keys like you have is just fine).
This is how you would sort using a descriptor as opposed to a key:
PFQuery *foodList = [PFQuery queryWithClassName:#"Food"];
[foodList whereKey:#"date" greaterThanOrEqualTo:minimumDate];
[foodList whereKey:#"date" lessThan:maximumDate];
NSSortDescriptor *orderBy = [NSSortDescriptor sortDescriptorWithKey:#"expiration_date" ascending:YES];
[foodList orderBySortDescriptor:orderBy];
I've found that the Parse Query is fairly unreliable once you start adding in multiple filters, and it may be a bug, but there doesn't seem to be much reason for it. What I've done, when I have multiple filters, is an NSPredicate.
NSPredicate *minPredicate = [NSPredicate predicateWithFormat:#"date >= %#", minimumDate];
NSPredicate *maxPredicate = [NSPredicate predicateWithFormat:#"date < %#", maximumDate];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:#[minPredicate,maxPredicate]];
PFQuery *foodList = [PFQuery queryWithClassName:#"Food" predicate:predicate];
[foodList orderByAscending:#"expiration_date"];
[foodList findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
}];
Another possibility is that your query is filtering for date, and then you order by "expiration_date" and I'm not sure if there's a disconnect between the two. Make sure your object nomenclature is what you're wanting.

QueryOp with recordID

I had a recordID.recordName (singleID in this example) and that I wanted to query with queryOp; after some searching and experimentation I managed to put this code together... which works, but is it really correct, is there a shorter path perhaps.
CKRecordID *wellKnownIDx = [[CKRecordID alloc] initWithRecordName:singleID];
CKReference *singleREX = [[CKReference alloc] initWithRecordID:wellKnownIDx action:CKReferenceActionDeleteSelf];
CKDatabase *publicDatabase = [[CKContainer containerWithIdentifier:#"iCloud.blah"] publicCloudDatabase];
NSPredicate *predicatex = [NSPredicate predicateWithFormat:#"recordID == %#",singleREX];
CKQuery *query = [[CKQuery alloc] initWithRecordType:#"Courses" predicate:predicatex];
CKQueryOperation *queryOp =[[CKQueryOperation alloc] initWithQuery:query];
queryOp.desiredKeys = #[#"record.recordID.recordName"];
queryOp.resultsLimit = 1;
queryOp.recordFetchedBlock = ^(CKRecord *results)
{
NSLog(#"Student Found %#",results.recordID.recordName);
};
queryOp.queryCompletionBlock = ^(CKQueryCursor *cursor, NSError *error)
{
NSLog(#"CKQueryCursor error %#", error);
};
[publicDatabase addOperation:queryOp];
What you have should work, but it looks like all you want to do is to fetch a record with a known recordID. There is no need to use a query for that. It's more code than necessary and will also require a query index on the field.
Instead, use the fetchRecordWithID method on CKDatabase:
https://developer.apple.com/library/ios/documentation/CloudKit/Reference/CKDatabase_class/index.html#//apple_ref/occ/instm/CKDatabase/fetchRecordWithID:completionHandler:

CloudKit : CKQuery showing error: error: The operation couldn’t be completed. (CKErrorDomain error 1.)

I working on iOS app implementing cloudkit but I need to query all the records with ID greater then a number. For example I have record with ID of 23:
here is my code:
CKContainer *myContainer = [CKContainer containerWithIdentifier:containerID];
CKDatabase *publicDatabase = [myContainer publicCloudDatabase];
CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:#"23"];
CKReference* recordToMatch = [[CKReference alloc] initWithRecordID:recordID action:CKReferenceActionNone];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"recordID >= %#", recordToMatch];
CKQuery *query = [[CKQuery alloc] initWithRecordType:recordType predicate:predicate];
[publicDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
if (error) {
NSLog(#"error: %#", error.localizedDescription);
}
else {
}
}];
But I'm getting the following error:
error: error: The operation couldn’t be completed. (CKErrorDomain error 1.)
Any of you knows how can I setup my NSPredicate in a way where I can get all the records with ID greater then 23 ?
I'll really appreciate your help.
For a query like this you could use a predicate like:
in Swift:
var predicate = NSPredicate(format: "recordID >= %#", CKRecordID(recordName: "23"))
In Objective C:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"recordID >= %#", [CKRecordID initWithRecordName:#"23"]];
Then I do assume that you created the CKRecords object originally while specifying this number. Otherwise recordID values will be assigned by CloudKit and will be a GUID.
Your recordID of 23 is stored as a CKRecordID type and not as a number thus you cannot use any numeric predicates like greater-than. You should create a new number field in your record for storing your integer IDs and query that instead.

Exclude own samples from healthkit queries

I'm writing an app that amongst other things, reads weight samples from HealthKit.
I'm also writing samples.
I'm trying to read the latest sample that isn't mine:
NSPredicate* non_fdct = [NSCompoundPredicate notPredicateWithSubpredicate:[HKQuery predicateForObjectsFromSource:[HKSource defaultSource]]];
NSSortDescriptor *last = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];
HKSampleQuery* query = [[HKSampleQuery alloc] initWithSampleType:[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass] predicate:non_fdct limit:1 sortDescriptors:#[last] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) { ... };
But I'm getting my own samples if they are the latest samples.
Any idea?
The way you have constructed the non_fdct predicate is not quite correct. Try this instead:
NSPredicate *non_fdct = [NSPredicate predicateFromString:#"%K != %#", HKPredicateKeyPathSource, [HKSource defaultSource]];

ios filter records using nsmutablearray filled with NSDictionary<FBGraphUser>* friend

I want to filter my friends list names. I had all friends list in NSMutable array
using this method i had list .
FBRequest* friendsRequest = [FBRequest requestForMyFriends];
[friendsRequest startWithCompletionHandler: ^(FBRequestConnection *connection,
NSDictionary* result,
NSError *error) {
friendList = [[NSMutableArray alloc]initWithArray:[result objectForKey:#"data"]];
selectedfriendList =[[NSMutableArray alloc]init];
[Tablefriendlist reloadData];
}];
I want to filter records through textfield but problem I dont know how to use nspredicatewithformat
I am trying this.. and its not filtering correct searched data.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.first_name contains[c] %#",searchText];
friendList = [NSMutableArray arrayWithArray:[friendList filteredArrayUsingPredicate:predicate]];
NSLog(#"friendlist %#",friendList);
[Tablefriendlist reloadData];
I want to get friendslist that match searchtext
problem is its fetching record but those record which contains searched characters only those.
e.g i searched sa
so it fetches records that contain character 's' and character 'a'
i want to seach records with sa e.g ::
when 'sa' is searched these records should be fetched
1:falsa
2:telsa
3:salad
what is happening in my code is this
1:falsa
2:telsa
3:yalst
4:salad
Try this
change predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.first_name contains[c] %#",searchText];
to
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"first_name contains[c] %#",searchText];

Resources