#ios #ios10 #cloudkit
#iOS #ios10 #cloudkit
Вопрос:
У меня есть приложение, которое поддерживает iOS 8 и выше. Я использовал CKDiscoverAllContactsOperation
для получения списка пользователей для целей совместного использования. Этот код отлично работает под iOS 8 и iOS 9. Но в iOS 10 блок завершения не возвращает ошибок, но он также не возвращает результатов, даже если они есть.
Я также заметил следующее сообщение в консоли:
<Ошибка>: получен обратный вызов прогресса обнаружения пользователя без идентификатора записи: { }
Это появляется между моментом запуска операции и вызовом блока завершения.
Вот соответствующий код:
CKDiscoverAllContactsOperation *op = [[CKDiscoverAllContactsOperation alloc] init];
op.discoverAllContactsCompletionBlock = ^(NSArray <CKDiscoveredUserInfo *> *userInfos, NSError *error) {
if (error) {
NSLog(@"Unable to get all app users: %@", error);
} else {
// process the found users
}
};
[container addOperation:op];
Я знаю, что CKDiscoverAllContactsOperation
это устарело с iOS 10 и было заменено на CKDiscoverAllUserIdentitiesOperation
. Но поскольку мое приложение поддерживает возврат к iOS 8, не должно быть никаких причин, по которым я не могу использовать тот же код даже под iOS 10. На самом деле, я все еще использую несколько других устаревших (начиная с iOS 10) классов CloudKit, и это единственный, который вызывает у меня проблему.
Ответ №1:
После некоторых исследований кажется, что CKDiscoverAllContactsOperation
это просто не работает должным образом под iOS 10. Вероятно, это ошибка в iOS 10, и ошибка будет отправлена в Apple. Но сейчас у меня есть пользователи, которые жалуются, и сейчас требуется обходной путь.
Самое простое решение — использовать новую операцию, когда она доступна, и использовать старую, когда ее нет.
Это привело к следующему базовому коду:
if ([CKDiscoverAllUserIdentitiesOperation class]) {
// Use the newer operation
CKDiscoverAllUserIdentitiesOperation *op = [[CKDiscoverAllUserIdentitiesOperation alloc] init];
NSMutableArray *users = [NSMutableArray array];
op.userIdentityDiscoveredBlock = ^(CKUserIdentity *identity) {
if (identity.hasiCloudAccount) {
DatabaseShareUser *user = [[DatabaseShareUser alloc] init];
user.recordId = identity.userRecordID;
user.username = [NSPersonNameComponentsFormatter localizedStringFromPersonNameComponents:identity.nameComponents style:NSPersonNameComponentsFormatterStyleDefault options:0];
[users addObject:user];
}
};
op.discoverAllUserIdentitiesCompletionBlock = ^(NSError *error) {
if (error) {
NSLog(@"Unable to get app users: %@", error);
completion(nil);
} else {
completion([users copy]);
}
};
[container addOperation:op];
} else {
// Use the old operation
CKDiscoverAllContactsOperation *op = [[CKDiscoverAllContactsOperation alloc] init];
op.discoverAllContactsCompletionBlock = ^(NSArray <CKDiscoveredUserInfo *> *userInfos, NSError *error) {
if (error) {
NSLog(@"Unable to get app users: %@", error);
completion(nil);
} else {
NSMutableArray *res = [NSMutableArray array];
for (CKDiscoveredUserInfo *userInfo in userInfos) {
DatabaseShareUser *user = [[DatabaseShareUser alloc] init];
user.recordId = userInfo.userRecordID;
user.username = userInfo.displayName;
[res addObject:user];
}
completion([res copy]);
}
};
[container addOperation:op];
}
DatabaseShareUser
это простой класс приложения, который хранит CKRecordID
и отображает имя каждого пользователя.
completion
это блок завершения, используемый методом, в котором находится этот код.
Комментарии:
1. Интересно, сообщила ли Apple о каком-либо прогрессе в исправлении этой ошибки. Спасибо.
2. @AnthonyC Не то, что я слышал. Поскольку существует разумный обходной путь, я не беспокоюсь об этом.