在iOS8自定义键盘扩展中获取完整字符串

在iOS8自定义键盘扩展中获取完整字符串,ios8,ios-app-extension,uiinputviewcontroller,Ios8,Ios App Extension,Uiinputviewcontroller,我正在为iOS 8创建自定义键盘扩展 我想得到用户在文本输入字段中写入的整个字符串 不幸的是,我遇到了两个主要问题: 1) 我在此回调中得到null: - (void)textDidChange:(id<UITextInput>)textInput 我想在用户当前编辑的文本输入中获取整个字符串 你建议我做什么 谢谢 我在documentContextAfterInput和documentContextBeforeInput字符串中遇到了相同的问题。我认为IOS8只返回插入点两侧的少

我正在为iOS 8创建自定义键盘扩展

我想得到用户在文本输入字段中写入的整个字符串

不幸的是,我遇到了两个主要问题:

1) 我在此回调中得到null:

- (void)textDidChange:(id<UITextInput>)textInput
我想在用户当前编辑的文本输入中获取整个字符串 你建议我做什么


谢谢

我在documentContextAfterInput和documentContextBeforeInput字符串中遇到了相同的问题。我认为IOS8只返回插入点两侧的少量字符。我认为这是有意的。

您可以始终使用一个可变数组来存储所有键入的文本,并在删除时删除最后一个字符(或者使用documentContextAfterInput/BeforeInput进行一些检测,以找到删除文本的位置,然后删除该部分)。这比仅仅调用“givemewhitstring”方法要复杂得多,但它适用于大多数情况,尤其是当他们只使用delete键键入和删除时。

我也遇到了同样的问题,我认为Xcode 6 beta 4已经解决了这个问题


只需将documentContextAfterInput附加到documentContextBeforeInput即可获得完整的输入字段文本。

在Xcode 6.1中,documentContextBeforeInput似乎只在模拟器中返回部分字符串,并在设备上正常工作

编辑: 好了,伙计们,这是我的代码:

-(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);
}
输出(仅在设备上)为: 2014-11-16 12:32:42.708键盘[2228:393159]谢谢!你好吗?

我找到了怎样做

- (void)doSomething{
    dispatch_async(inputQueue, ^{
        [self getAllString];
    });
    return;
}
首先用dispatch_async和您自己的队列包装您的方法

#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];
}

对于每个代理方法,您都必须少睡一会儿

结果:

文本框

012, 345! 6789
0123. 4567! 89012 '34567890.' 123456789
控制台

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


嘿,你检查过了吗
-(NSString*)textInRange:(uitextange*)range
?问题是(id)textInput给了我一个零object@Francescu你让它在你这边起作用了吗?我很想听一听……谢谢!看起来是故意的。。如果你能找到一个好的观察方法让我知道。我相信它返回的“一小撮”字符是那些出现在一个典型的结束标点符号之后的字符,比如句号“.”或新行空格。你们能访问
输出吗
?它发生在句号+下一个大写字母之后。如果字母不是大写,它还会加上下一行。谢谢,这是一个很好的选择。你能想象如果用户复制粘贴的文本会发生什么吗?或者如果键盘是在非空文本字段中启动的?谢谢:)如果键盘是在非空文本字段上启动的,您很可能希望处理它,如果它在录制的字符串中没有检测到ContextAfter/BeforeInput,那么它将默认为您在没有此方法的情况下尝试执行的任何操作。我不确定您尝试使用它做什么,所以我真的不知道这是否可以接受。如果它是为了帮助文本预测或其他什么,如果文本预测在那种情况下不是基于一个完整的句子,那就好了,但在其他情况下,它肯定不是理想的。对于复制粘贴的文本,您可以对before/afterinput字符串的各个部分进行深入分解,并对其进行比较,以潜在地找到其放置的位置(或者如果字符串为空,则仅获取全部或大部分复制/粘贴部分)。很抱歉,不能再明确了。我要做的是获取所有文本并建议同义词和更好的语法。看到了吗?它返回整个字符串?字符串的长度无关紧要?documentContextBeforeInput返回插入点之前的内容,documentContextAfterInput返回插入点之后的内容。因此,如果合并两个字符串,则无论内容有多长,都会得到整个内容。它不会在换行符(
\n
)之前“看到”。。(至少在beta 5中,还没有检查beta 6)它在beta 4中被修复,然后在beta 5中再次出现:o更正,对于新行
\n
和其他标点符号,如“!”和“.”。它之前也无法获取文本。请解释:您正在谈论的是哪个问题?您的意思是说,无论我的字符串长度如何,documentContextBeforeInput将始终返回完整字符串?如果是这样,那就是大新闻!你确定吗?你能详细说明一下吗(截图太棒了)?如果是这样的话,这确实是一个大新闻,是对XCode 6.0的一个巨大改变。@nurne我刚刚下载了XCode 6.1.1 GM进行测试,
documentContextBeforeInput
似乎仍然只返回由句点或其他常见句子完成标记描述的部分字符串。例如:“谢谢!你好吗?”与“谢谢,你好吗?”
documentContextBeforeInput
将只返回第二句中的完整字符串。请检查我的编辑。。。但现在我有了一个邪恶的想法…你在键盘上测试什么应用程序?我在SDK 8.2上制作的Notes应用程序中进行测试,并在iOS 8.1上运行,在主Notes应用程序的文本框中进行测试。第一个util来自brilliant hack:)您是否分发了带有此代码的键盘?我想知道苹果对此有何看法
-(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;
}
012, 345! 6789
0123. 4567! 89012 '34567890.' 123456789
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