CKQueryOperation got error "No operations present in request" randomly - ios

I'm trying to fetch some records from Cloud Server w/ the code snippet below. It returns records w/o any error in most times:
CKQuery * query = [[CKQuery alloc] initWithRecordType:#"MyTable"
predicate:[NSPredicate predicateWithFormat:#"accountID = 1"]];
CKQueryOperation * recordFetchOperation = [[CKQueryOperation alloc] initWithQuery:query];
recordFetchOperation.database = [[CKContainer defaultContainer] privateCloudDatabase];
recordFetchOperation.recordFetchedBlock = ^(CKRecord *record) {
// get records succeed some times
};
recordFetchOperation.queryCompletionBlock = ^(CKQueryCursor *cursor, NSError *operationError) {
if (operationError) [self _handleError:operationError];
};
... // some other operations
NSOperationQueue * queue = [[NSOperationQueue alloc] init];
[queue addOperations:#[recordFetchOperation, ...]
waitUntilFinished:NO];
But sometimes, it returns error:
{
NSDebugDescription = "CKInternalErrorDomain: 1009";
NSLocalizedDescription = "No operations present in request";
NSUnderlyingError = "Error Domain=CKInternalErrorDomain Code=1009 \"No operations present in request\" UserInfo={NSLocalizedDescription=No operations present in request}";
}
I've checked the error code, it's CKErrorInvalidArguments, which as doc said
Bad client request (bad record graph, malformed predicate)
I've no idea how this error comes and how to handle this error, unlike CKErrorNetworkUnavailable error, it does not have CKErrorRetryAfterKey value in error.userInfo for me to send the request after a time interval.
Btw, when I got this error, all my operations will have this error w/o any record returned.

Related

"The user is blocked from live streaming." (Domain=com.google.GTLRErrorObjectDomain Code=403)

When I'm trying to perform request for inserting of a broadcast I receive error:
Error Domain=com.google.GTLRErrorObjectDomain Code=403 "The user is blocked from live streaming."
UserInfo={GTLRStructuredError=GTLRErrorObject 0x28027ad30: {code:403
errors:[1] message:"The user is blocked from live streaming."},
NSLocalizedDescription=The user is blocked from live streaming.}
I have started receiving this error today. Before, everything has been working fine. I have tested on several accounts and had not any luck.
Code:
GTLRYouTube_LiveBroadcastSnippet *broadcastSnippet= [[GTLRYouTube_LiveBroadcastSnippet alloc] init];
[broadcastSnippet setTitle:title];
[broadcastSnippet setScheduledStartTime:[GTLRDateTime dateTimeWithDate:self.beginOfStream]]; // current date + 1 minute.
[broadcastSnippet setScheduledEndTime:[GTLRDateTime dateTimeWithDate:[NSDate dateWithTimeIntervalSinceNow:80000]]];
GTLRYouTube_LiveBroadcastStatus *status = [[GTLRYouTube_LiveBroadcastStatus alloc] init];
[status setPrivacyStatus:[StreamSettings youtubeStringForPrivacyStatus:[privacyStatus intValue]]];
GTLRYouTube_LiveBroadcastContentDetails *details = [self streamDetailsWith:latency];
GTLRYouTube_LiveBroadcast *broadcast = [[GTLRYouTube_LiveBroadcast alloc] init];
[broadcast setKind:#"youtube#liveBroadcast"];
[broadcast setSnippet:broadcastSnippet];
[broadcast setStatus:status];
GTLRYouTubeQuery_LiveBroadcastsInsert *query = [GTLRYouTubeQuery_LiveBroadcastsInsert queryWithObject:broadcast
part:#"id, snippet, contentDetails,status"];
GTLRYouTubeService *service = self.youTubeService;
__strong id <YouTubeHelperDelegate> strongDelegate = self.delegate;
[service executeQuery:query completionHandler:^(GTLRServiceTicket *ticket,
GTLRYouTube_LiveBroadcast *returnedBrocast,
NSError *error) {
if (error) {
NSLog(#"%#", error); //Here is place I got an error
}
}];
If the logged in user does not have more than 1000 subscribers he can't go live using a mobile app, as mentioned in link:
https://support.google.com/youtube/answer/2853834?hl=en

add a contact to a group using Contacts framework

I created a group using contacts group, and then I want to add a contact to the group.
NSPredicate *predicate = [CNGroup predicateForGroupsWithIdentifiers:#[[[NSUserDefaults standardUserDefaults]objectForKey:#"groupIDentifier"]]];
NSArray *groups = [store groupsMatchingPredicate:predicate error:&saveError];
CNMutableContact *contact = [[CNMutableContact alloc] init];
contact.familyName = #"Doe";
contact.givenName = #"John";
CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:[CNPhoneNumber phoneNumberWithStringValue:#"312-555-1212"]];
contact.phoneNumbers = #[homePhone];
CNSaveRequest *request = [CNSaveRequest new];
CNGroup *group = [groups firstObject];
[request addContact:contact toContainerWithIdentifier:group.identifier];
if (![store executeSaveRequest:request error:&saveError]) {
NSLog(#"error = %#", saveError);
}
The error is:
error = Error Domain=CNErrorDomain Code=200 "Updated Record Does Not
Exist" UserInfo={CNInvalidRecordIdentifiers=(
"45FFBB0D-C74B-4A14-8293-9099EA7DEF81:ABGroup" ), NSLocalizedDescription=Updated Record Does Not Exist,
NSLocalizedFailureReason=The save request failed because it updates a
record that does not exist or has already been deleted.}
I also tried using:
[request addMember:contact toGroup:[groups firstObject]];
and this case, the error is:
error = Error Domain=CNErrorDomain Code=200 "Updated Record Does Not Exist" UserInfo={CNInvalidRecords=(
"<CNContact: 0x7f8ce97aa640: identifier=7CC6BC1D-1B23-48DA-8282-06115F542A97:ABPerson, givenName=John, familyName=Doe, organizationName=, phoneNumbers=(\n \"<CNLabeledValue: 0x600001873cc0: identifier=68277209-3AE4-40AF-9EEA-DF0E1D01883C, label=_$!<Home>!$_, value=<CNPhoneNumber: 0x600000433300: stringValue=312-555-1212, initialCountryCode=(null)>>\"\n), emailAddresses=(\n), postalAddresses=(\n)>" ), NSLocalizedFailureReason=The save request failed because it updates a record that does not exist or has already been deleted., NSLocalizedDescription=Updated Record Does Not Exist}
The crazy thing I found is: I need to call both addMember and addContact, to actually make the contact add to the group.
CNGroup *group = [groups firstObject];
[request addMember:contact toGroup:group];
[request addContact:contact toContainerWithIdentifier:nil];
if (![store executeSaveRequest:request error:&saveError]) {
NSLog(#"error = %#", saveError);
}
Response from the Apple Support:
You must save the contact, and group, separately. Then check to see if they exist, before the contact can be added to that group. Otherwise, you will receive the same error you are seeing in the output.
Create the group
Execute the save of the contact
Check if the Contact and the Group both exist
Add contact to group using addMember
This actually serves the purpose, but I have no clue why I have to actually make the two types of requests.

Update(change) user-defined metadata of the AWS S3 object with iOS SDK

Can anybody help with that?
I tried to use AWSS3ReplicateObjectRequest setting bucket, key and replicateSource properties to point the same existing S3 file, setting metadataDirective to AWSS3MetadataDirectiveReplace and assigning new user-defined metadata. In that case I have error:
Error Domain=com.amazonaws.AWSGeneralErrorDomain Code=3 "The operation
couldn’t be completed. (com.amazonaws.AWSGeneralErrorDomain error 3.)"
UserInfo=0x7ae60ef0 {Message=The request signature we calculated does not
match the signature you provided. Check your key and signing method. ...
Have I missed something here?
(AWS iOS SDK v2.2.4)
Update:
AWSS3 *s3 = [AWSS3 S3ForKey:s3Key];
AWSS3ReplicateObjectRequest *request = [[AWSS3ReplicateObjectRequest alloc] init];
request.bucket = MYAmazonS3BucketName;
request.key = self.s3ObjectKey;
request.replicateSource = [NSString stringWithFormat:#"%#/%#",
MYAmazonS3BucketName,
self.s3ObjectKey];
request.contentType = #"application/octet-stream";
NSDictionary *metadata = #{#"type" : #"my_type",
#"note" : #"the_note"};
request.metadata = metadata;
request.metadataDirective = AWSS3MetadataDirectiveReplace;
[[s3 replicateObject:request] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(#"Error: %#", task.error);
}
else {
NSLog(#"Result: %#", task.result);
}
return nil;
}];
The authentication is performed with Cognito. I can upload/download/delete the object, can get the metadata separately.

Exception when trying to convert HeartRate from HealthKitStore

I am working on my first iPhone App: a simple app showing the heartRate results from HealthKit in a nice way. My first step is to show the results as a raw text. But unfortunately I'm getting an exception at the following line, telling me: "thread 1 signal SIGABRT". Does someone know, what I did wrong and hint me in a direction?
double usersBeatsPerMinute = [quantity doubleValueForUnit:[HKUnit countUnit]];
The rest of the code looks like this:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// Set up an HKHealthStore, asking the user for read/write permissions. The profile view controller is the
// first view controller that's shown to the user, so we'll ask for all of the desired HealthKit permissions now.
// In your own app, you should consider requesting permissions the first time a user wants to interact with
// HealthKit data.
if ([HKHealthStore isHealthDataAvailable]) {
NSSet *writeDataTypes = [self dataTypesToWrite];
NSSet *readDataTypes = [self dataTypesToRead];
[self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) {
if (!success) {
NSLog(#"You didn't allow HealthKit to access these read/write data types. In your app, try to handle this error gracefully when a user decides not to provide access. The error was: %#. If you're using a simulator, try it on a device.", error);
return;
}
}];
}
HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
// Since we are interested in retrieving the user's latest sample
// we sort the samples in descending order by end date
// and set the limit to 1
// We are not filtering the data, and so the predicate is set to nil.
NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];
// construct the query & since we are not filtering the data the predicate is set to nil
HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:weightType predicate:nil limit:1 sortDescriptors:#[timeSortDescriptor] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {
// if there is a data point, dispatch to the main queue
if (results) {
dispatch_async(dispatch_get_main_queue(), ^{
HKQuantitySample *quantitySample = results.firstObject;
// pull out the quantity from the sample
HKQuantity *quantity = quantitySample.quantity;
double usersBeatsPerMinute = [quantity doubleValueForUnit:[HKUnit countUnit]];
_HeartRateResults.text = [NSString stringWithFormat:#"%# lbs", [NSNumberFormatter localizedStringFromNumber:#(usersBeatsPerMinute) numberStyle:NSNumberFormatterNoStyle]];
});
}
}];
// do not forget to execute the query after its constructed
[_healthStore executeQuery:query];}
There was a comment in the documentation ("These samples use count/time units") I didn't quite understand, so I did a little searching and tried it out and was able to get a value I manually put into the Health app using this:
double rate = [mostRecentQuantity doubleValueForUnit:[[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]]];
I haven't seen unitDividedByUnit before. Here's the article I pulled it from.

NSURLErrorDomain code=-1005 from GKLeaderboard loadScoresWithCompletionHandler:

I am receiving the following error in a callback to loadScoresWithCompletionHandler:
Error Domain=NSURLErrorDomain Code=-1005
"The operation couldn’t be completed. (NSURLErrorDomain error -1005.)"
Other calls to Game Center both before and afterwards succeed. (They operate on various threads). If have initialized the leaderboard request as follows:
GKLeaderboard *leaderboard = [[GKLeaderboard alloc] init];
leaderboard.identifier = leaderboardIdentifier; // valid identifier
leaderboard.playerScope = GKLeaderboardPlayerScopeFriendsOnly;
leaderboard.range = NSMakeRange(1, 100); // max. allowed range.
leaderboard.timeScope = GKLeaderboardTimeScopeAllTime;
[leaderboard loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) {
// ...
}];
What is going on here and how can I overcome this problem?
The calls to loadScoresWithCompletionHandler: are made from an operation on an NSOperationQueue whose task it is to issue requests for scores (I am interested in each localPlayerScore) to several leaderboards and wait for all responses. The first response already carries the error.
UPDATE -1005 denotes kCFURLErrorNetworkConnectionLost; the underlying cause is still unclear.
UPDATE If I send only a single request (instead of as so far typically 6 in parallel) I receive error NSURLErrorDomain -1001, which denotes kCFURLErrorTimedOut, or GKErrorDomain 3 ...
For some reason this alternative call does not lead to errors:
GKLeaderboard *leaderboard =
[[GKLeaderboard alloc] initWithPlayers:#[ GKLocalPlayer.localPlayer ]];
leaderboard.identifier = leaderboardIdentifier;
leaderboard.timeScope = GKLeaderboardTimeScopeAllTime;
[leaderboard loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) {
// ...
}];
Problem solved.

Resources