Синхронные операции над токенами не следует вызывать в главном потоке, т.к. они могут выполняться продолжительное время. К тому же логика работы с токеном через ридеры (iR301-UL, iR301-U, bR301, bR301 BLE, JaCarta USB) и NFC смарт-карту отличается.
При работе через ридеры токен всегда подключен к мобильному устройству и к нему можно получить доступ из любого ViewController вашего приложения. Но при работе через NFC смарт-карту открывается сессия, ограниченная минимум 20 секундами, которая отображает системный ViewController для индикации пользователю о необходимости поднести NFC смарт-карту к мобильному устройству и только в эту сессию можно выполнять операции на токене. После закрытия сессии связь с токеном прерывается.
Таким образом при работе с NFC, если на первом ViewController получить список токенов со смарт-карты, а на втором ViewController выпонить какие-либо операции над токеном, то в нем придется повторять все действия по поиску токена.
Для решения данной проблемы необходимо использовать методы execBlock или execBlockWithParameters, которые:
Таким образом, эти методы обеспечивают единообразную работу с токеном вне зависимости от способа подключения.
Важно
Не следует вызывать методы execBlock или execBlockWithParameters внутри handler метода getTokensWithAlertMessage, т.к. NFC сессия уже открыта и открытие повторной приведет к ошибке.
Общий пример использования
Требуется прочитать список сертификатов у токена, который был получен с помощью методов startWithQueue, getTokensWithQueue или getTokensWithAlertMessage.
Подобный вариант использования представлен в следующих примерах SDK: JaCartaSample_ObjC и JaCartaSample_Swift.
// Получение token при помощи методов
// [startWithQueue:notificationCenter:tokenAttached:tokenDetached:watcherStopped:],
// [getTokensWithQueue:attempts:attemptsDelay:predicate:handler:],
// или [getTokensWithAlertMessage:predicate:handler:].
// id<JCToken> token = ...;
// ...
NSDictionary* parameters = [[NSDictionary alloc] initWithObjectsAndKeys:
@"You can scan NFC-tags by holding them behind the top of your device", JCTokenParamNFCAlertMessage,
nil
];
// 1. Асинхронное выполнение кода.
// Для смарт-карты с ридером это будет обычный асинхронный вызов.
// Для NFC смарт-карты это будет асинхронный вызов c открывшейся новой NFC сессией.
[token execBlockWithParameters:parameters block:^(NSError * _Nullable error) {
if (error) {
// 2. Обработка ошибки.
// Может вернуться в случае неудачного открытия NFC сессии.
return;
}
// 3. Чтение сертификатов с токена.
JCCertificateListResult *result = [token readCertificates];
dispatch_async(dispatch_get_main_queue(), ^{
// 4. Обработка результата чтения сертификатов в главном потоке
});
}];
Пример выполнения синхронных операций токена на смарт-карте, подключенной к ридеру, сразу после его получения
Требуется прочитать список сертификатов у токена, который был получен с помощью метода getTokensWithQueue.
Используется метод execBlock и синхронные операции вызываются внутри него.
Подобный вариант использования представлен в следующих примерах SDK: JCSignSample_ObjC и JCSignSample_Swift.
// 1. Проверка наличия readerWatcher.
// Объект существует, если инициализация менеджера прошла успешно
// и был передан хотя бы один из следующих флагов: JCReadersIR301AndBR301, JCReadersBR301BLEAndBR500
id<JCReaderWatcher> readerWatcher = JCManager.defaultManager.readerWatcher;
if (!readerWatcher) {
// 2. Обработка отсутствия объекта readerWatcher
return;
}
// 3. Запуск процесса поиска токенов
BOOL started = [readerWatcher
getTokensWithQueue:dispatch_get_main_queue()
attempts:5
attemptsDelay:1.0
predicate:^BOOL(id<JCToken> _Nonnull token, BOOL * _Nonnull stop) {
// 5. Для примера берем первый попавшийся токен.
*stop = YES;
return YES;
}
handler:^(NSArray<id<JCToken>> * _Nullable tokens, NSError * _Nullable error) {
if (error) {
// 6. Обработка ошибки поиска токенов
return;
}
id<JCToken> token = tokens[0];
// 7. Асинхронное выполнение кода.
[token execBlock:^(NSError * _Nullable error) {
// 8. Чтение сертификатов с токена.
JCCertificateListResult *result = [token readCertificates];
dispatch_async(dispatch_get_main_queue(), ^{
// 9. Обработка результата чтения сертификатов в главном потоке
});
}];
}];
if (!started) {
// 4. Обработка ситуации, когда процесс поиска токенов не запустился.
return;
}
Пример выполнения синхронных операций токена на NFC смарт-карте сразу после его получения
Требуется прочитать список сертификатов у токена, который был получен с помощью метода getTokensWithAlertMessage.
Методы execBlock или execBlockWithParameters не используются, а синхронные операции вызываются внутри handler метода getTokensWithAlertMessage.
Подобный вариант использования представлен в следующих примерах SDK: JCSignSample_ObjC и JCSignSample_Swift.
// 1. Проверка наличия nfcWatcher.
// Объект существует, если инициализация менеджера прошла успешно
// и был передан флаг JCReadersNFC
id<JCNFCWatcher> nfcWatcher = JCManager.defaultManager.nfcWatcher;
if (!nfcWatcher) {
// 2. Обработка отсутствия объекта nfcWatcher
return;
}
[nfcWatcher
getTokensWithAlertMessage:@"You can scan NFC-tags by holding them behind the top of your device"
predicate:^BOOL(id<JCToken> _Nonnull token, BOOL * _Nonnull stop) {
// 3. Для примера берем первый попавшийся токен.
*stop = YES;
return YES;
}
handler:^(NSArray<id<JCToken>> * _Nullable tokens, NSError * _Nullable error) {
if(error) {
// 4. Обработка ошибки поиска токенов.
// NFC сессия будет закрыта.
return;
}
// 5. Чтение сертификатов с токена.
JCCertificateListResult *result = [tokens[0] readCertificates];
dispatch_async(dispatch_get_main_queue(), ^{
// 6. Обработка результата чтения сертификатов в главном потоке
});
// NFC сессия будет закрыта и связь с токеном исчезнет.
}];