UITextDocumentProxy adjustTextPositionByCharacterOffset 问题

UITextDocumentProxy adjustTextPositionByCharacterOffset Issue

我正在使用 Swift 为 iOS 8 开发自定义键盘。我正在尝试编写一个在光标两侧插入文本的函数。

我在我的 class 中定义了这个继承自 UIInputViewController

的函数
func nestedTag(tag: NSString) {
    let proxy = self.textDocumentProxy as UITextDocumentProxy
    proxy.insertText(tag)
    proxy.insertText(tag)
    proxy.insertText(" ")
    proxy.adjustTextPositionByCharacterOffset(-1 * (1 + tag.length))

例如,如果我用 !!! 调用 nestedTag,我希望得到键盘输入的文本字段:

!!!<CURSOR>!!!<SPACE> 

问题是,如果我在没有输入的情况下专注于空文本字段时调用此函数,则会得到错误的结果。

!!!!!!<SPACE><CURSOR>

此外,如果我在关注填充的文本字段时调用此函数,我会得到不同的错误行为。

前面的文本字段:

helloworld

后面的文本字段:

hello w!!!!!! orld

在此示例中,光标确实向左移动了 4 个字符,但是这看起来好像对 adjustTextPositionByCharacterOffset 的调用是在 对 [ 的三个调用之前调用的=19=] 尽管事实并非如此(见代码)。

两个 UITextDocumentProxy 方法的 documentation 似乎非常简单且不言自明,而且我似乎没有看到其他在线人遇到过这个问题。我似乎无法弄清楚我做错了什么以获得这些奇怪的结果。谢谢你的时间。

我正在苦苦挣扎,但我几乎没有发现,所以我分享它

textDocumentProxy 提供了 6 个方法

(insert, move cursor, delete, afterInput, beforeInput, hasText)

这 6 个方法和异步方法一样需要一些时间。 (每种方法需要不同的时间) 例如)原始序列:move insert move -> 结果:insert move move

所以,我尝试在调用每个方法之前等待一段时间。

semaphoredispatch_async 以及 dispatch_after 包装每个方法, 我们可以像同步方法一样等待它们。

inputQueue = dispatch_queue_create("happynewyear", 0);
inputQueue2 = dispatch_queue_create("happynewyear2", 0);


-(void)moveCursor:(NSInteger)num{
     dispatch_async(inputQueue2, ^{
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);

        dispatch_after(delay(TIME_INTERVAL), inputQueue, ^{
            [self.textDocumentProxy adjustTextPositionByCharacterOffset:num];
            NSLog(@"moveCursor : %ld",(long)num);
            dispatch_semaphore_signal(sema);
        });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    });
}

-(void)insertText:(NSString*)string{
    dispatch_async(inputQueue2, ^{
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);

        dispatch_after(delay(TIME_INTERVAL), inputQueue, ^{
            [self.textDocumentProxy insertText:string];
            NSLog(@"insertText : %@",string);
            dispatch_semaphore_signal(sema);
        });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    });
}

-(void)deleteBackward:(NSInteger)num{
    dispatch_async(inputQueue2, ^{
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);

        dispatch_after(delay(TIME_INTERVAL), inputQueue, ^{

            for (int i = 0; i<num; ++i) {
                [self.textDocumentProxy deleteBackward];
            }
            NSLog(@"deleteBackward : %ld",(long)num);
            dispatch_semaphore_signal(sema);
        });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    });
}

延迟函数...

inline static dispatch_time_t delay(double delay){
    return dispatch_time(
                         DISPATCH_TIME_NOW,
                         delay * NSEC_PER_SEC
                         );
}

我用 TIME_INTERVAL 作为 0.01

这个技巧让你的代码保持顺序。

我正在尝试其他方法(afterInput、beforeInput ...),如上,

如果我解决了,我会回来

swift:

let TIME_INTERVAL: DispatchTime = DispatchTime.init(uptimeNanoseconds: UInt64(0.01))
let inputQueue = DispatchQueue(label: "input")
let inputQueue2 = DispatchQueue(label: "input2")
func deleteBackWard(num:NSInteger) -> Void {
    self.inputQueue2.async {
        let sema = DispatchSemaphore.init(value: 0)
        self.inputQueue.asyncAfter(deadline: self.TIME_INTERVAL) {
            for _ in 0...num {
                self.textDocumentProxy.deleteBackward()
            }
            sema.signal()
        }
        sema.wait(timeout: DispatchTime.distantFuture)
    }
}


func insertTextAsync(text: String) -> Void {
    self.inputQueue2.async {
        let sema = DispatchSemaphore.init(value: 0)
        self.inputQueue.asyncAfter(deadline: self.TIME_INTERVAL) {
            self.textDocumentProxy.insertText(text)
            sema.signal()
        }
        sema.wait(timeout: DispatchTime.distantFuture)
    }
}


func moveCursor(num:NSInteger) -> Void {
    self.inputQueue2.async {
        let sema = DispatchSemaphore.init(value: 0)
        self.inputQueue.asyncAfter(deadline: self.TIME_INTERVAL) {
            self.textDocumentProxy.adjustTextPosition(byCharacterOffset: num)
            sema.signal()
        }
        sema.wait(timeout: DispatchTime.distantFuture)
    }
}

第 Jeonghan Joo