I'm creating a Custom Keyboard Extension for iOS 8.
I want to get the whole string that the user wrote in the text input field.
Unfortunately I stumble in to two main problems:
1) I get null in this callback:
- (void)textDidChange:(id<UITextInput>)textInput
2) I only get partial String When I call these methods:
- [self.textDocumentProxy documentContextAfterInput];
- [self.textDocumentProxy documentContextBeforeInput];
I want to get the whole string in the text input the user is currently editing
what do you suggest i do?
Thanks!
I found How To.
- (void)doSomething{
dispatch_async(inputQueue, ^{
[self getAllString];
});
return;
}
First Wrap Your Method With dispatch_async and your own queue.
#define DELAY_LENGTH 0.01
-(void)getAllString{
id<UITextDocumentProxy> proxy = self.textDocumentProxy;
NSString* before = [proxy documentContextBeforeInput];
NSString* after = [proxy documentContextAfterInput];
NSMutableArray* afterArray = [NSMutableArray arrayWithCapacity:10];
while (after) {
unsigned long afterLength = [after length];
if(afterLength <= 0){
break;
}
[afterArray addObject:after];
[NSThread sleepForTimeInterval:DELAY_LENGTH];
[proxy adjustTextPositionByCharacterOffset:afterLength];
[NSThread sleepForTimeInterval:DELAY_LENGTH];
after = [proxy documentContextAfterInput];
}
NSMutableArray* beforeArray = [NSMutableArray arrayWithCapacity:10];
[NSThread sleepForTimeInterval:DELAY_LENGTH];
before = [proxy documentContextBeforeInput];
while (before) {
unsigned long beforeLength = [before length];
if (beforeLength <= 0) {
break;
}
[beforeArray addObject:before];
[NSThread sleepForTimeInterval:DELAY_LENGTH];
[proxy adjustTextPositionByCharacterOffset:-beforeLength];
[NSThread sleepForTimeInterval:DELAY_LENGTH];
before = [proxy documentContextBeforeInput];
}
NSLog(@"afterArray: %@",[self getArrayString:afterArray reverse:false]);
NSString* beforeString = [self getArrayString:beforeArray reverse:true];
NSLog(@"beforArray: %@",beforeString);
[NSThread sleepForTimeInterval:DELAY_LENGTH];
[proxy adjustTextPositionByCharacterOffset:beforeString.length];
}
There are two utils :
@implementation NSArray (Reverse)
- (NSArray *)reversedArray {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count]];
NSEnumerator *enumerator = [self reverseObjectEnumerator];
for (id element in enumerator) {
[array addObject:element];
}
return array;
}
@end
and
-(NSString*)getArrayString : (NSArray*)array
reverse : (BOOL)isReverse{
NSArray* tar = isReverse ? [array reversedArray] : array;
NSMutableString* result = [NSMutableString stringWithCapacity:10];
for (NSString* string in tar) {
[result appendString:string];
}
return result;
}
YOU HAVE TO SLEEP LITTLE FOR EACH PROXY METHOD.
result :
TextBox
012, 345! 6789
0123. 4567! 89012 '34567890.' 123456789
Console
2015-03-18 21:04:15.034 moveCursor[39413:2692914] afterArray:
2015-03-18 21:04:15.035 moveCursor[39413:2692914] beforArray: 012, 345! 6789
0123. 4567! 89012 '34567890.' 123456789
I ran into the same problem with the documentContextAfterInput and documentContextBeforeInput strings. I think that IOS8 only returns a handful of characters on either side of the insertion point. I think this is intentional.
You could always have a mutable array you store all typed text in, and remove the last character when deleting(or maybe do some detection with documentContextAfterInput/BeforeInput to find the spot to delete text, then remove that portion). This is more complicated than just calling a 'giveMeWholeString' method, but it would work for most cases, especially if they were only typing and deleting with the delete key.
I had the same problem and I think it has been fixed with Xcode 6 beta 4.
Just append documentContextAfterInput to documentContextBeforeInput to get the full input field text.
in Xcode 6.1 it seems that documentContextBeforeInput returns partial string only in simulator and works fine on the device.
Edit:
ok guys here's my code:
-(void)addPeriod{
if (![self endsWithCharacter:'.' String:[[((UIInputViewController*)self.delegate).textDocumentProxy documentContextBeforeInput] stringByReplacingOccurrencesOfString:@" " withString:@""]]) {
[((UIInputViewController*)self.delegate).textDocumentProxy deleteBackward];
[((UIInputViewController*)self.delegate).textDocumentProxy insertText:@"."];
}
}
- (BOOL) endsWithCharacter: (unichar) c String:(NSString*)str
{
NSLog(@"%@",str);
NSUInteger length = [str length];
return (length > 0) && ([str characterAtIndex: length - 1] == c);
}
and the output (on the device only) is:
2014-11-16 12:32:42.708 Keyboard[2228:393159] Thanks!howareyou?