Как определить, активирована ли пользовательская клавиатура из приложения-контейнера клавиатуры?
Мне было интересно, есть ли метод, который позволит мне обнаружить из приложения-контейнера клавиатуры, была ли активирована соответствующая клавиатура в приложении настроек устройства.
Например, я заинтересован в добавлении простой функции "шагов" внутри контейнерного приложения, где шаг 1 будет "активировать клавиатуру", а шаг 2 будет зависеть от завершения этапа 1. Как таковой, мне интересно выяснить, есть ли способ определить, активировано ли расширение клавиатуры?
Спасибо!
Ответы
Ответ 1
Вот метод, который я использовал в одном из моих проектов. Я думаю, это то, о чем вы просили, надеюсь, что это вам поможет.
- (BOOL)isCustomKeyboardEnabled {
NSString *bundleID = @"com.company.app.customkeyboard"; // Replace this string with your custom keyboard bundle ID
NSArray *keyboards = [[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] objectForKey:@"AppleKeyboards"]; // Array of all active keyboards
for (NSString *keyboard in keyboards) {
if ([keyboard isEqualToString:bundleID])
return YES;
}
return NO;
}
Ответ 2
На всякий случай вот Swift-версия Курта, блестящий и потрясающий ответ:
func isKeyboardExtensionEnabled() -> Bool {
guard let appBundleIdentifier = Bundle.main.bundleIdentifier else {
fatalError("isKeyboardExtensionEnabled(): Cannot retrieve bundle identifier.")
}
guard let keyboards = UserDefaults.standard.dictionaryRepresentation()["AppleKeyboards"] as? [String] else {
// There is no key 'AppleKeyboards' in NSUserDefaults. That happens sometimes.
return false
}
let keyboardExtensionBundleIdentifierPrefix = appBundleIdentifier + "."
for keyboard in keyboards {
if keyboard.hasPrefix(keyboardExtensionBundleIdentifierPrefix) {
return true
}
}
return false
}
Ответ 3
В текущем documentation указано By default, your extension and its containing app have no direct access to each other’s containers
.
Также указано, что контейнерное приложение может совместно использовать данные с клавиатурой следующим образом:
// Create and share access to an NSUserDefaults object.
NSUserDefaults *mySharedDefaults = [[NSUserDefaults alloc]
initWithSuiteName:@"com.example.domain.MyShareExtension"];
// Use the shared user defaults object to update the user account.
[mySharedDefaults setObject:theAccountName forKey:@"lastAccountName"];
Подробнее об этом: Общение и сохранение данных между приложениями с группами приложений
Препятствие № 1. Согласно документации, для этого для работы RequestsOpenAccess
в plist должно быть установлено значение YES
, поскольку оно может получить следующие возможности:
Возможность использовать общий контейнер с клавиатурами, содержащими приложение, который позволяет такие функции, как предоставление пользовательского управления лексикой Пользовательский интерфейс в содержащем приложении
Запрос на полный доступ для простого случая, подобного этому, определенно не является предпочтительным на моей стороне.
Препятствие нет 2. Используя это знание установки NSUserDefault
, мне следует подумать о методе, где это можно установить на место. Но нет общедоступного метода, указывающего расширение. Так что теперь это тупик.
-
[Обновить 1]
Не очень важно, но все же стоит сказать: метод делегата shouldAllowExtensionPointIdentifier
в сочетании с константой UIApplicationKeyboardExtensionPointIdentifier
может иметь дело с отказом от пользовательских клавиатур. Идентификаторы точки расширения не являются уникальными идентификаторами расширения, а являются их типом.
Подробнее об этом: Можно ли отключить пользовательские клавиатуры (iOS8) для моего приложения?
-
[Обновить 2]
Другой вопрос с той же проблемой, но без решения: Как определить расширение приложения включено в приложении app на iOS 8?
-
Это незавершенный ответ, в котором говорится о моих выводах, которые я надеюсь обновлять в ближайшие дни, если я найду решение.
Ответ 4
Вы можете использовать эту функцию (Swift 3 и 4), чтобы проверить, что пользовательский расширение клавиатуры имеет открытый доступ или нет:
func isOpenAccessGranted() -> Bool{
if #available(iOS 10.0, *) {
let originalString = UIPasteboard.general.string
UIPasteboard.general.string = "Sour LeangChhean"
if UIPasteboard.general.hasStrings {
UIPasteboard.general.string = originalString ?? ""
return true
}else{
UIPasteboard.general.string = ""
return false
}
} else {
// Fallback on earlier versions
if UIPasteboard.general.isKind(of: UIPasteboard.self) {
return true
}else{
return false
}
}
}