Last active
August 29, 2015 14:07
-
-
Save ChristianKienle/df8b00a6a87494df6367 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@class CKRecordID; | |
@interface CKCPartialErrorItem : NSObject | |
@property (strong) NSError *error; | |
@property (strong) CKRecordID *recordID; | |
@end | |
@class CKRecord; | |
@interface NSError (Convenience) | |
@property (readonly) BOOL isCloudKitError; | |
#pragma mark - Server Record Change Error | |
@property (readonly) BOOL isServerRecordChangedError; | |
@property (readonly) CKRecord *ancestorRecord; | |
@property (readonly) CKRecord *serverRecord; | |
@property (readonly) CKRecord *clientRecord; | |
#pragma mark - Retryable Errors | |
@property (readonly) BOOL isRequestRateLimitedError; | |
@property (readonly) BOOL isServiceUnavailableError; | |
@property (readonly) BOOL isRetryableError; | |
// returns -1 if there is no retry entry in the user info dictionary of this error | |
// or if isRequestRateLimitedError is NO. | |
@property (readonly) NSTimeInterval retryAfterInSeconds; | |
#pragma mark - Partial Failiure Error | |
@property (readonly) BOOL isPartialFailureError; | |
// The user info dictionary of a partial failure error contains a dictionary | |
// for the 'CKPartialErrorsByItemIDKey'. This dictionary is returned by this property. | |
@property (readonly) NSDictionary *partialErrorsByItemID; | |
// A batch request can partially fail. If so there are real errors that describe the | |
// reason as to why the whole batch request failed. Those erros (+ the record ID) | |
// is returned by realPartialErrorItems. | |
@property (readonly) NSSet *realPartialErrorItems; // CKCPartialErrorItem | |
// If a batch request partially failed then partialErrorsByItemID also contains | |
// the errors (+ the record ID) for the records that failed because the batch request | |
// failed as a whole because of the erros that are contained in realPartialErrorItems. | |
@property (readonly) NSSet *batchRequestPartialErrorItems; // CKCPartialErrorItem | |
// Indicates an error that was generated because a batch failed as a whole. | |
@property (readonly) BOOL isBatchRequestFailedError; | |
// Indicates a real error. | |
@property (readonly) BOOL isRealPartialError; | |
#pragma mark - Misc | |
@property (readonly) BOOL isUnknownItemError; | |
// Request size too large (too many records in the request - make smaller batches) | |
@property (readonly) BOOL isLimitExceededError; | |
@property (readonly) BOOL isQuotaExceededError; | |
@end | |
/// IMPLEMENTATION | |
#import "NSError+Convenience.h" | |
#import <CloudKit/CloudKit.h> | |
@implementation CKCPartialErrorItem | |
- (NSString *)description { | |
return [NSString stringWithFormat:@"%@ ID: %@ - error: %@", [super description], self.recordID, self.error]; | |
} | |
@end | |
@implementation NSError (Convenience) | |
- (BOOL)isCloudKitError { | |
return [self.domain isEqualToString:CKErrorDomain]; | |
} | |
- (BOOL)isCloudKitErrorWithCode:(CKErrorCode)cloudKitCode { | |
return (self.isCloudKitError && self.code == cloudKitCode); | |
} | |
- (BOOL)isServerRecordChangedError { | |
return [self isCloudKitErrorWithCode:CKErrorServerRecordChanged]; | |
} | |
- (CKRecord *)ancestorRecord { | |
return self.userInfo[CKRecordChangedErrorAncestorRecordKey]; | |
} | |
- (CKRecord *)serverRecord { | |
return self.userInfo[CKRecordChangedErrorServerRecordKey]; | |
} | |
- (CKRecord *)clientRecord { | |
return self.userInfo[CKRecordChangedErrorClientRecordKey]; | |
} | |
#pragma mark - Retryable Errors | |
- (BOOL)isRequestRateLimitedError { | |
return [self isCloudKitErrorWithCode:CKErrorRequestRateLimited]; | |
} | |
- (BOOL)isServiceUnavailableError { | |
return [self isCloudKitErrorWithCode:CKErrorServiceUnavailable]; | |
} | |
- (BOOL)isRetryableError { | |
return (self.isRequestRateLimitedError || self.isServiceUnavailableError); | |
} | |
- (NSTimeInterval)retryAfterInSeconds { | |
if(self.isRequestRateLimitedError == NO) { | |
return -1.0; | |
} | |
NSNumber *retryAfter = self.userInfo[CKErrorRetryAfterKey]; | |
if(retryAfter == nil) { | |
return -1.0; | |
} | |
return retryAfter.doubleValue; | |
} | |
#pragma mark - Partial Failiure Error | |
- (BOOL)isPartialFailureError { | |
return [self isCloudKitErrorWithCode:CKErrorPartialFailure]; | |
} | |
- (NSDictionary *)partialErrorsByItemID { | |
return self.userInfo[CKPartialErrorsByItemIDKey]; | |
} | |
- (NSSet *)realPartialErrorItems { | |
NSDictionary *partialErrorsByItemID = self.partialErrorsByItemID; | |
NSMutableSet *errorItems = [NSMutableSet new]; | |
for(CKRecordID *recordID in partialErrorsByItemID) { | |
NSError *error = partialErrorsByItemID[recordID]; | |
if(error.isRealPartialError) { | |
CKCPartialErrorItem *item = [CKCPartialErrorItem new]; | |
item.error = error; | |
item.recordID = recordID; | |
[errorItems addObject:item]; | |
} | |
} | |
return errorItems; | |
} | |
- (NSSet *)batchRequestPartialErrorItems { | |
NSDictionary *partialErrorsByItemID = self.partialErrorsByItemID; | |
NSMutableSet *errorItems = [NSMutableSet new]; | |
for(CKRecordID *recordID in partialErrorsByItemID) { | |
NSError *error = partialErrorsByItemID[recordID]; | |
if(error.isBatchRequestFailedError) { | |
CKCPartialErrorItem *item = [CKCPartialErrorItem new]; | |
item.error = error; | |
item.recordID = recordID; | |
[errorItems addObject:item]; | |
} | |
} | |
return errorItems; | |
} | |
- (BOOL)isBatchRequestFailedError { | |
return [self isCloudKitErrorWithCode:CKErrorBatchRequestFailed]; | |
} | |
- (BOOL)isRealPartialError { | |
return !self.isBatchRequestFailedError; | |
} | |
#pragma mark - Misc | |
- (BOOL)isUnknownItemError { | |
return [self isCloudKitErrorWithCode:CKErrorUnknownItem]; | |
} | |
- (BOOL)isLimitExceededError { | |
return [self isCloudKitErrorWithCode:CKErrorLimitExceeded]; | |
} | |
- (BOOL)isQuotaExceededError { | |
return [self isCloudKitErrorWithCode:CKErrorQuotaExceeded]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment