CloudKit: Couldn't renew our secure session - ios

I'm trying to request a record from cloudkit with the following code:
CKContainer *myContainer = [CKContainer defaultContainer];
CKDatabase *publicDatabase = [myContainer publicCloudDatabase];
CKDatabase *privateDatabase = [myContainer privateCloudDatabase];
[publicDatabase saveRecord:artworkRecord completionHandler:^(CKRecord *artworkRecord, NSError *error){
if (!error) {
NSLog(#"saved!!!");
CKDatabase *publicDatabase = [[CKContainer containerWithIdentifier:#"Artwork"] publicCloudDatabase];
CKRecordID *artworkRecordID = [[CKRecordID alloc] initWithRecordName:#"115"];
[publicDatabase fetchRecordWithID:artworkRecordID completionHandler:^(CKRecord *artworkRecord, NSError *error) {
if (error) {
NSLog(#"error fetching %#", error);
}
else
{
NSLog(#"loading record %#", artworkRecord );
}
}];
when I make the request I get this error: "errors === <CKError 0x1780533b0: "Internal Error" (1/4000); "Couldn't renew our secure session">"
But the weird thing is I can save more records with no issues.
I'm using a iPad wifi to test this code
I'll really appreciate your help.

This error is incorrectly returned if CloudKit couldn't reach the server to get its configuration. This most commonly happens if you're trying to access a container that hasn't been provisioned by the server or if there's an issue with your network connection.
This was a bug in CloudKit and more recent iOS and OS X releases should provide a better error message in this case.

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

CKSubscription of type CKSubscriptionOptionsFiresOnRecordUpdate doesn't work

I setup a CKSubscription with the following code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"TRUEPREDICATE"];
CKSubscription *subscription = [[CKSubscription alloc] initWithRecordType:#"RecordTypeName"
predicate:predicate
subscriptionID:#"Subscription1"
options:CKSubscriptionOptionsFiresOnRecordCreation | CKSubscriptionOptionsFiresOnRecordUpdate];
CKDatabase *privateDatabase = [[CKContainer defaultContainer] privateCloudDatabase];
[privateDatabase saveSubscription:subscription completionHandler:^(CKSubscription * _Nullable subscription, NSError * _Nullable error) {
if (error) {
NSLog(#"Failed to subscribe.");
}
}];
In application:didReceiveRemoteNotification: I get notified when a new record is added, but I never get notified when an existing record is updated.
I've tried updating records from both the CloudKit dashboard and from another device signed into the same account.
I'm testing on iOS 9 beta 5.
Its a known bug that update notifications are not working.
[CKFetchNotificationChangesOperation sometimes does not return UPDATE, DELETE notifications
[CloudKit push notifications on record update stopped working
[https://forums.developer.apple.com/thread/7288][3]

CloudKit: creatorUserRecordID of CKRecord Issue (or Bug?)

After iOS 8.3, if the record is created by the current account, its creatorUserRecordID will be like
CKRecordID: [Some Address]; defaultOwner:(_defaultZone:defaultOwner)
And then if fetch this recordID using fetchRecordWithID:completionHandler: from CKDatabase, it will always return error like
CKError [Some Address]: "Unknown Item" (11/2003); server message = "Record not found"; uuid = [Some UUID]; container ID = [Some Container ID]
I never encounter this issue before.
Is it a bug, or should I fetch record from recordID like this ( defaultOwner ) in other way?
EDIT (add sample code)
- (void)postMoodFeed:(NSString *)moodFeed
{
CKRecord *moodRecord = [[CKRecord alloc] initWithRecordType:#"Mood"];
moodRecord[#"moodFeed"] = moodFeed
[[[CKContainer defaultContainer] publicCloudDatabase] saveRecord:moodRecord completionHandler:^(CKRecord *record, NSError *error) {
[self queryMyMood];
}];
}
- (void)queryMyMood
{
// currentUserRecordID is fetched from fetchUserRecordIDWithCompletionHandler: of CKContainer
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"creatorUserRecordID = %#", currentUserRecordID];
CKQuery *query = [[CKQuery alloc] initWithRecordType:#"Mood" predicate:predicate];
[[[CKContainer defaultContainer] publicCloudDatabase] performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
if (results) {
for (CKRecord *eachRecord in results) {
// Following logs are all __defaultOwner__
NSLog(#"%#", eachRecord.creatorUserRecordID.recordName);
[[[CKContainer defaultContainer] publicCloudDatabase]fetchRecordWithID:eachRecord.creatorUserRecordID completionHandler:^(CKRecord *record, NSError *error) {
// All following logs are "Unknown item" error
NSLog(#"%#", error);
}];
}
}
}];
}
EDIT July 2, 2015
That is a bug.
After reporting to Apple, they fixed this issue in iOS 9 Beta 2.
Indeed it looks like new functionality.
What you could do is first testing if the eachRecord.creatorUserRecordID.recordName == "defaultOwner" and if that's the case you could fetch the record for the ID that you got from the currentUserRecordID
But it would be better to not use the creatorUserRecordID for any functionality in your app. You could better add a new CKReference field and always fill it with the currentUserRecordID. Then even if you have a process that migrates data, you would still know who created that record originally.
Maybe this will help: I've found that if you use [CKFetchRecordsOperation fetchCurrentUserRecordOperation] at the beginning of your app's workflow you won't have defaultOwner CKRecordIDs come out of nowhere.

CloudKit fetchRecordWithID error: "Fetching asset failed"

I am trying to fetch a record with CloudKit and it fails with the following error: "Fetching asset failed" I confirmed (via the CloudKit Dashboard) that the record exists in my public database and the default zone and the default container (not a custom container). Here is my code:
CKContainer *container = [CKContainer defaultContainer];
CKDatabase *publicDatabase = [container publicCloudDatabase];
CKRecordID *artworkRecordID = [[CKRecordID alloc] initWithRecordName:#"1C0DCC08-71D3-4C47-A417-DB92D2EECB67"];
[publicDatabase fetchRecordWithID:artworkRecordID completionHandler:^(CKRecord *artworkRecord, NSError *error) {
if (error) {
// Error handling for failed fetch from public database
}
else {
// Display the fetched record
}
}];
I had a user get this because they weren’t signed in to iCloud in their iPhone Settings.
As you can see in your screenshot the error code is 4 which is a network error
See xcdoc://?url=developer.apple.com/library/ios/documentation/CloudKit/Reference/CloudKit_constants/index.html#//apple_ref/c/tdef/CKErrorCode
Try switching to 3G or WiFi to see if there is different behavior.
If you go to your app settings, is mobile data enabled?
Can you run the code from the simulator?

Deleting all HKQuantitySamples

I want to delete all HKQuantitySamples that my app has saved in the Health App for a certain HKQuantityType, how would I do that?
I can see the function
deleteObject:withCompletion:
in the Apple Documentation, but I do not really understand how to use it. Can somebody show an example maybe?
EDIT: I now use the following code for deleting:
I have saved my food information as a HKCorrelation and set my Local Food ID in the Correlations metadata HKMetadataKeyExternalUUID key.
For deletion I am fetching all the HKCorrelation objects between startDate and endDate and then if one of these fetched objects matches the Local Food ID I am looking for:
- I delete every object in that Correlation,
- Followed by deleting the Correlation itself
HKCorrelationType *foodType = [HKObjectType correlationTypeForIdentifier:HKCorrelationTypeIdentifierFood];
NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];
HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:foodType predicate:predicate limit:HKObjectQueryNoLimit sortDescriptors:nil resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {
if (!results) {
NSLog(#"An error occured fetching the user's tracked food. In your app, try to handle this gracefully. The error was: %#.", error);
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
for (HKCorrelation *foodCorrelation in results) {
if([[foodCorrelation.metadata valueForKey:HKMetadataKeyExternalUUID] isEqualToString:food_id_I_want_to_delete]) {
NSSet *objs = foodCorrelation.objects;
for (HKQuantitySample *sample in objs) {
[self.healthStore deleteObject:sample withCompletion:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"Success. delete sample");
}
else {
NSLog(#"delete: An error occured deleting the sample. In your app, try to handle this gracefully. The error was: %#.", error);
}
}];
}
[self.healthStore deleteObject:foodCorrelation withCompletion:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"Success. delete %#", [foodCorrelation.metadata valueForKey:HKMetadataKeyExternalUUID]);
}
else {
NSLog(#"delete: An error occured deleting the Correlation. In your app, try to handle this gracefully. The error was: %#.", error);
}
}];
return;
}
}
});
}];
[self.healthStore executeQuery:query];

Resources