I'm writing a custom keyboard for iOS and I'd like to detect when the user copies some text. I've read that you can use the NSNotificationCenter
along with UIPasteboardChangedNotification
in order to do this.
However, it seems my selector isn't getting fired when the user copies text. When I put a breakpoint on the addObserver
line it appears to get skipped over although breakpoints immediately before and after it are hit. Here is the code I am using:
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
// Register copy notifications
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleCopy:", name: UIPasteboardChangedNotification, object: nil)
}
func handleCopy(sender: NSNotification) {
//todo: handle the copied text event
}
Can anyone determine what I'm missing?
Edit:
I noticed that the notification fires if I programmatically update the pasteboard after registering the notification, but I still can't figure out why it's not being hit if the user uses the context menu "copy".
My not a perfect but work enough solution. I already use it in keyboard.
@interface MyPrettyClass : UIViewController
@end
@implementation MyPrettyClass
@property (strong, nonatomic) NSTimer *pasteboardCheckTimer;
@property (assign, nonatomic) NSUInteger pasteboardchangeCount;
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
_pasteboardchangeCount = [[UIPasteboard generalPasteboard] changeCount];
//Start monitoring the paste board
_pasteboardCheckTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(monitorBoard:)
userInfo:nil
repeats:YES];
}
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[self stopCheckingPasteboard];
}
#pragma mark - Background UIPasteboard periodical check
- (void) stopCheckingPasteboard{
[_pasteboardCheckTimer invalidate];
_pasteboardCheckTimer = nil;
}
- (void) monitorBoard:(NSTimer*)timer{
NSUInteger changeCount = [[UIPasteboard generalPasteboard]; changeCount];
if (changeCount != _pasteboardchangeCount) { // means pasteboard was changed
_pasteboardchangeCount = changeCount;
//Check what is on the paste board
if ([_pasteboard containsPasteboardTypes:pasteboardTypes()]){
NSString *newContent = [UIPasteboard generalPasteboard].string;
_pasteboardContent = newContent;
[self tryToDoSomethingWithTextContent:newContent];
}
}
}
- (void)tryToDoSomethingWithTextContent:(NSString)newContent{
NSLog(@"Content was changed to: %@",newContent);
}
@end
You cannot use NSNotificationCenter since the keyboard extension is a different process.
Cocoa includes two types of notification centers: The NSNotificationCenter class manages notifications within a single process. The NSDistributedNotificationCenter class manages notifications across multiple processes on a single computer.
Try this solution: https://stackoverflow.com/a/28436058/649379 which uses CFNotifications. Don't forget to enable App Groups to get access to the shared container.
More code here: https://github.com/cxa/AppExtensionCommunicator & https://github.com/mutualmobile/MMWormhole
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With