首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >保存CKRecord时的错误处理

保存CKRecord时的错误处理
EN

Stack Overflow用户
提问于 2015-09-17 09:38:16
回答 3查看 1K关注 0票数 2

我正在寻找一个在保存CKRecord时正确处理错误的示例。根据Apple docs的说法,我应该“使用error对象中的信息来确定问题是否有解决方法”。

我知道error对象有一个userInfo字典,但是我如何确定字典的键是什么以及如何处理错误呢?

下面的示例说明了我当前如何保存CKRecord

代码语言:javascript
复制
    CKRecord *record = [[CKRecord alloc] initWithRecordType:@"MyRecordType"];
[record setValue:[NSNumber numberWithInt:99] forKey:@"myInt"];

[db saveRecord:record completionHandler:^(CKRecord *savedPlace, NSError *error) {
    // handle errors here
    if (savedPlace) {
        NSLog(@"save successful");
    }else{
        NSLog(@"save unsuccessful");
    }
    if (error) {
        NSLog(@"Error saving %@", error.localizedDescription);
    }

}];

我如何改进这段代码,以便为潜在的保存问题提供解决方案?

EN

回答 3

Stack Overflow用户

发布于 2015-09-17 15:53:32

在我的库EVCloudKitDao中,我有一个单独的方法,它将根据错误代码返回错误类型。根据类型的不同,您可以决定要做什么。以下是该方法:

代码语言:javascript
复制
public enum HandleCloudKitErrorAs {
    case Success,
    Retry(afterSeconds:Double),
    RecoverableError,
    Fail
}

public static func handleCloudKitErrorAs(error:NSError?, retryAttempt:Double = 1) -> HandleCloudKitErrorAs {
    if error == nil {
        return .Success
    }
    let errorCode:CKErrorCode = CKErrorCode(rawValue: error!.code)!
    switch errorCode {
    case .NetworkUnavailable, .NetworkFailure, .ServiceUnavailable, .RequestRateLimited, .ZoneBusy, .ResultsTruncated:
        // Use an exponential retry delay which maxes out at half an hour.
        var seconds = Double(pow(2, Double(retryAttempt)))
        if seconds > 1800 {
            seconds = 1800
        }
        // Or if there is a retry delay specified in the error, then use that.
        if let userInfo = error?.userInfo {
            if let retry = userInfo[CKErrorRetryAfterKey] as? NSNumber {
                seconds = Double(retry)
            }
        }
        NSLog("Debug: Should retry in \(seconds) seconds. \(error)")
        return .Retry(afterSeconds: seconds)
    case .UnknownItem, .InvalidArguments, .IncompatibleVersion, .BadContainer, .MissingEntitlement, .PermissionFailure, .BadDatabase, .AssetFileNotFound, .OperationCancelled, .NotAuthenticated, .AssetFileModified, .BatchRequestFailed, .ZoneNotFound, .UserDeletedZone, .InternalError, .ServerRejectedRequest, .ConstraintViolation:
        NSLog("Error: \(error)")
        return .Fail;
    case .QuotaExceeded, .LimitExceeded:
        NSLog("Warning: \(error)")
        return .Fail;
    case .ChangeTokenExpired,  .ServerRecordChanged:
        NSLog("Info: \(error)")
        return .RecoverableError
    default:
        NSLog("Error: \(error)") //New error introduced in iOS...?
        return .Fail;
    }
}

在CloudKit方法的回调中,您可以像这样使用此函数:

代码语言:javascript
复制
func loadContacts(retryCount:Double = 1) {        
    // Look who of our contact is also using this app.
    EVCloudKitDao.publicDB.allContactsUserInfo({ users in
            EVLog("AllContactUserInfo count = \(users.count)");
            Async.main{
                self.contacts = users
                self.tableView.reloadData()
            }
        }, errorHandler: { error in
            switch EVCloudKitDao.handleCloudKitErrorAs(error, retryAttempt: retryCount) {
            case .Retry(let timeToWait):
                Async.background(after: timeToWait) {
                    self.loadContacts(retryCount + 1)
                }
            case .Fail:
                Helper.showError("Something went wrong: \(error.localizedDescription)")
            default: // For here there is no need to handle the .Success, .Fail and .RecoverableError
                break
            }
    })
}

在上面的例子中,我使用了一个单独的错误回调处理程序。您也可以在CloudKit方法回调中直接调用它。只需首先检查是否有错误。

票数 2
EN

Stack Overflow用户

发布于 2015-09-17 11:00:50

下面是一个实现,在这个实现中,我通过在存储在userInfo字典中的建议重试时间间隔后重试保存来处理CKErrorNetworkFailure的常见错误。

代码语言:javascript
复制
-(void)saveRecord:(CKRecord*)record toDatabase:(CKDatabase*)database{
[database saveRecord:record completionHandler:^(CKRecord *record, NSError *error) {
    if (error==nil) {
        NSLog(@"The save was successful");
        //Do something
    }else{
        NSLog(@"Error saving with localizedDescription: %@", error.localizedDescription);
        NSLog(@"CKErrorCode = %lu", [error code]);

        if ([error code]==CKErrorNetworkFailure) {
            double retryAfterValue = [[error.userInfo valueForKey:CKErrorRetryAfterKey] doubleValue];
            NSLog(@"Error code network unavailable retrying after %f", retryAfterValue);
            NSTimer *timer = [NSTimer timerWithTimeInterval:retryAfterValue target:self selector:@selector(testOutCloudKit) userInfo:nil repeats:NO];
            [timer fire];
        }
    }
}];

}

票数 1
EN

Stack Overflow用户

发布于 2016-10-13 04:53:08

在Swift 3中,我这样处理我的CloudKit错误:

代码语言:javascript
复制
privateDB.perform(myQuery, inZoneWith: nil)  {records, error in
    if error != nil {
        print (error?.localizedDescription)
        if error?._code == CKError.notAuthenticated.rawValue {
            // Solve problems here...
        }

请注意,在编写CKError之后,将从代码完成显示的列表中选择CKError.notAuthenticated。

希望这能有所帮助!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32621306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档