In iOS 8, when develop a custom keyboard and set RequestsOpenAccess property to YES in info.plist, there is a toggle button at Settings-> Add New Keyboard named "Allow Full Access". How does the custom keyboard code know that the user enabled or disabled this toggle?
问题:
回答1:
UPDATE 08/23/2017 for iOS 10 compatibility:
func isOpenAccessGranted() -> Bool{
UIPasteboard.general.string = "CHECK"
return UIPasteboard.general.hasStrings
}
iOS 8:
-(BOOL)isOpenAccessGranted{
return [UIPasteboard generalPasteboard];
}
Please note that the simulator will always tell you that you have Full Access so for this to work properly you need to run it from a device.
回答2:
This is the simplest answer by far and doesn't require you to setup app groups. It is tested in production on the app store.
+ (BOOL)isOpenAccessGranted
{
return [UIPasteboard generalPasteboard];
}
回答3:
For iOS 10 (Beta 5) they changed the UIPasteboard API but I found the following to work:
let originalString = UIPasteboard.general.string
UIPasteboard.general.string = "TEST"
if UIPasteboard.general.hasStrings
{
UIPasteboard.general.string = originalString
hasFullAccess = true
}
else
{
hasFullAccess = false
}
回答4:
I've been testing this today in iOS 10 and getting access to the pasteboard doesn't appear to be enough. In iOS 10 you can set the pasteboard to a var without full access. Here's a solution I came up with...
func checkFullAccess() -> Bool
{
var hasFullAccess = false
if #available(iOSApplicationExtension 10.0, *) {
let pasty = UIPasteboard.general
if pasty.hasURLs || pasty.hasColors || pasty.hasStrings || pasty.hasImages {
hasFullAccess = true
} else {
pasty.string = "TEST"
if pasty.hasStrings {
hasFullAccess = true
pasty.string = ""
}
}
} else {
// Fallback on earlier versions
var clippy : UIPasteboard?
clippy = UIPasteboard.general
if clippy != nil {
hasFullAccess = true
}
}
return hasFullAccess
}
Testing to see if the pasteboard has some content returns false with full access off, even when there's content on the pasteboard. Of course it could actually be empty so after all those tests you can safely attempt to set something on the pasteboard without worrying about replacing something that's already there. If you do have access and the pasteboard had content then the test would have returned true, if you don't have access then you can't overwrite something that was there.
HTH, Mike
回答5:
Update: No need for App Group to be enabled, as others have mentioned, just check for access to the pasteboard:
- (BOOL)isFullAccessGranted
{
return !![UIPasteboard generalPasteboard];
}
NOTE: The following no longer works, even if you do have App Group enabled...
For a custom keyboard with an App Group enabled, the following is a quick, reliable way of testing for the state of the "Allow Full Access" switch:
func isOpenAccessGranted() -> Bool {
let fm = NSFileManager.defaultManager()
let containerPath = fm.containerURLForSecurityApplicationGroupIdentifier(
"group.com.example")?.path
var error: NSError?
fm.contentsOfDirectoryAtPath(containerPath!, error: &error)
if (error != nil) {
NSLog("Full Access: Off")
return false
}
NSLog("Full Access: On");
return true
}
回答6:
For iOS 10 using Swift 2.3 (if you don't want to convert your files to Swift 3.0)
func isOpenAccessGranted() -> Bool {
if #available(iOSApplicationExtension 10.0, *) {
let originalString = UIPasteboard.generalPasteboard().string
UIPasteboard.generalPasteboard().string = "Test"
if UIPasteboard.generalPasteboard().hasStrings {
UIPasteboard.generalPasteboard().string = originalString
return true
} else {
return false
}
} else {
return UIPasteboard.generalPasteboard().isKindOfClass(UIPasteboard)
}
}
回答7:
This code works for me, I also on App Groups : https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html#//apple_ref/doc/uid/TP40012582-CH26-SW61
May be it will work without App Groups also.
And I used this code :
if(isOpenAccessGranted()){
NSLog("FULL ACCESS ON")
}
else{
NSLog("FULL ACCESS OFF")
}
}
func isOpenAccessGranted() -> Bool {
return UIPasteboard.generalPasteboard().isKindOfClass(UIPasteboard)
}
回答8:
Useful Swift solution by @hoiberg42:
func isOpenAccessGranted() -> Bool {
return UIPasteboard.generalPasteboard().isKindOfClass(UIPasteboard)
}
Works like a charm!
回答9:
iOS 11 no longer requires any hacks.
override var hasFullAccess: Bool {
if #available(iOS 11.0, *) {
return super.hasFullAccess// super is UIInputViewController.
}
if #available(iOS 10.0, *) {
let original: String? = UIPasteboard.general.string
UIPasteboard.general.string = " "
let val: Bool = UIPasteboard.general.hasStrings
if let str = original {
UIPasteboard.general.string = str
}
return val
}
return UIPasteboard.general.isKind(of: UIPasteboard.self)
}
回答10:
just use
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
AudioServicesPlaySystemSound(1104);
});
the tirck is ,when the full access is enabled ,the sound will play ,if not ,because it's call is in the background thread will no block the main thread
回答11:
A swift solution
if let test = UIPasteboard.generalPasteboard() as? UIPasteboard{
NSLog("Full Access: On")
return true
}else{
NSLog("Full Access: Off")
return false
}
inside the above function of course.
回答12:
Today, for iOS 9.2, you can check opened access by:
func isOpenAccessGranted() -> Bool {
return UIPasteboard(name: "checkOpenedAccess", create: true) != nil
}
回答13:
Apps with app group can use :
func isOpenAccessGranted() -> Bool {
let fm = NSFileManager.defaultManager()
let containerPath = fm.containerURLForSecurityApplicationGroupIdentifier(
AppGroup)?.path
return fm.isWritableFileAtPath(containerPath!)
}
回答14:
For those of you who are using iOS 10 and Objective-C this will work as intended.
- (BOOL)hasFullAccess
{
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
NSString *originalString = pasteboard.string;
pasteboard.string = @"TEST";
if (pasteboard.hasStrings) {
pasteboard.string = originalString;
return YES;
} else {
return NO;
}
}
回答15:
iOS11 and above is easy.
iOS10 Solution: Check all the copy-able types, if one of them is available, you have full access otherwise not.
-- Swift 4.2--
override var hasFullAccess: Bool
{
if #available(iOS 11.0, *){
return super.hasFullAccess// super is UIInputViewController.
}
if #available(iOSApplicationExtension 10.0, *){
if UIPasteboard.general.hasStrings{
return true
}
else if UIPasteboard.general.hasURLs{
return true
}
else if UIPasteboard.general.hasColors{
return true
}
else if UIPasteboard.general.hasImages{
return true
}
else // In case the pasteboard is blank
{
UIPasteboard.general.string = ""
if UIPasteboard.general.hasStrings{
return true
}else{
return false
}
}
} else{
// before iOS10
return UIPasteboard.general.isKind(of: UIPasteboard.self)
}
}