I'm programmatically copying an image to the UIPasteboard, and I want to determine if the copy was successful or not. Specifically, I'm creating an custom keyboard on iOS 8, where some of the keys will copy an image to the pasteboard for the user to paste in a textfield.
UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];
[pasteBoard setImage:[UIImage imageNamed:anImage]];
To do this, the user must allow "Full Access" on the keyboard. So I either have to have a way to determine if Full Access is on (not sure how to check this), or determine if the copy to the pasteboard was successful. If Full Access isn't on, I have to alert the user to turn it on in order for the keyboard to work.
When the copy does fail (due to Full Access being off), I get the log message from UIPasteboard:
UIPasteboard - failed to launch pasteboardd. Make sure it's installed in UIKit.framework/Support
Is there anyway to catch this at runtime?
Any suggestions on how to achieve this would be appreciated!
I seem to have found a solution for now. This comes from the Apple Developer forums (user Andrew Boyd), and is the only post I could find that correctly solves the problem.
- (BOOL)testFullAccess
{
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"yourAppGroupID"]; // Need to setup in Xcode and Developer Portal
NSString *testFilePath = [[containerURL path] stringByAppendingPathComponent:@"testFullAccess"];
NSError *fileError = nil;
if ([[NSFileManager defaultManager] fileExistsAtPath:testFilePath]) {
[[NSFileManager defaultManager] removeItemAtPath:testFilePath error:&fileError];
}
if (fileError == nil) {
NSString *testString = @"testing, testing, 1, 2, 3...";
BOOL success = [[NSFileManager defaultManager] createFileAtPath:testFilePath
contents: [testString dataUsingEncoding:NSUTF8StringEncoding]
attributes:nil];
return success;
} else {
return NO;
}
}
In order for this to work, you must configure an app group, which your keyboard extension will use in an attempt to communicate with your keyboard app. To do this, follow Apple's instructions on Configuring App Groups. Use the identifier you create there to replace the string yourAppGroupID
in the above code. Then this method will attempt to communicate with the main app for your keyboard. If successful, then we can conclude that Full Access is on.
I hope this solution helps someone else until Apple [hopefully] adds a quicker check if the user enabled Full Access or not. Not to mention, hopefully they create an easier way for the user to enable full access outside of the settings menu.
I'm doing this in swift:
func isOpenAccessGranted() -> Bool {
return UIPasteboard.generalPasteboard().isKindOfClass(UIPasteboard)
}
Should work in Obj-C as well:
- (BOOL)isOpenAccessGranted() {
return [[UIPasteboard generalPasteboard] isKindOfClass:UIPasteboard.class];
}