2014-10-09 9 views
6

My UITextView delegata loguje pozycji daszka przy użyciu następujących:UITextView dostarczenie nieprawdziwych daszka rect

- (void)textViewDidBeginEditing:(UITextView *)textView 
{ 
    CGPoint cursorPosition = [textView caretRectForPosition:textView.selectedTextRange.start].origin; 
    NSLog(@"cursor: %@", NSStringFromCGPoint(cursorPosition)); 
} 

Ale zgłaszane pozycja zawsze jest niedokładna. W szczególności raportuje pozycję poprzednie kursor - na przykład, jeśli kliknę raz wewnątrz widoku tekstu w pozycji (x, y), a następnie na zewnątrz, a następnie z powrotem w (x2, y2), po drugim kliknięciu (x, y) współrzędne są rejestrowane.

W rzeczywistości problemem jest selectedTextRange - zgłaszany jest poprzedni zakres.

Czego mi brakuje? Nie widzę innej metody delegatów, której mogę użyć zamiast tego.

Odpowiedz

4

Wartość selectedTextRange będzie starsza tylko po rozpoczęciu edycji, jeszcze się nie zmieniła. Podczas obliczania parametru cursorPostion z zaznaczonym tekstem stare wartości prowadzą do starej pozycji. Musimy więc obliczyć nową pozycję wewnątrz innego uczestnika, który zgłasza po zmianach wyboru. Otrzymasz poprawne odczyty za pomocą poniższego kodu. Nadzieję, że pomoże

-(void)textViewDidChangeSelection:(UITextView *)textView 
{ 
    CGPoint cursorPosition = [textView caretRectForPosition:textView.selectedTextRange.start].origin; 
    NSLog(@"cursor start: %@", NSStringFromCGPoint(cursorPosition)); 
} 
+1

Jest to bardzo zaskakujące, ponieważ metoda delegata to * zrobił * BeginEditing, a nie * będzie * BeginEditing. Czy masz źródło lub jakieś inne informacje? Nie mogę użyć sugerowanej metody, ponieważ będzie ona uruchamiana za każdym razem, gdy użytkownik zmieni zaznaczenie, które nie jest tym, czego szukam. –

+1

Nie, nie mam odniesienia do dokumentacji dotyczącej kopii zapasowej. Moje twierdzenie jest oparte wyłącznie na eksperymentach, które zrobiłem. Ale czy nie jest oczywiste, że _didBegin_ rzeczywiście odnosi się do początku jakiegoś procesu edycji. Jeśli spróbujemy narysować analogię z __UITextField__ _delegates_; _didBeginEditing_ nie oznacza, że ​​treść została zmieniona. Tylko moje przemyślenia :) – Gandalf

+0

To kazało mi wyciągać włosy na długie godziny. Dzięki. – BallpointBen

2

To dość obrzydliwe, ale jedno rozwiązanie jest wprowadzenie krótkie opóźnienie przed odczytaniem wywołanie metody:

UITextView *textView = note.object; 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
    CGPoint cursorPosition = [textView caretRectForPosition:textView.selectedTextRange.start].origin; 
    NSLog(@"cursor: %@", NSStringFromCGPoint(cursorPosition)); 
}); 
+1

bravo !!! Pozwoliło mi to zaoszczędzić ponad 8 godzin na wyszukiwaniu. – TonyTony

+0

Dziękujemy! Korzystanie z opóźnienia również zadziałało na mnie! Nie wiem, czy istnieje jakieś inne rozwiązanie, ponieważ 'textViewDidBeginEditing' jest ostatnią metodą, która jest wywoływana po rozpoczęciu edycji textView. Rozwiązanie @Gandalf jest również dobre, ale zostaje wywołane tylko wtedy, gdy wybór jest inny niż poprzedni wybór. – SFF

1

Właściwie znalazłem inne rozwiązanie tego.

Możesz użyć UIKeyboardDidShowNotification, aby uzyskać bieżący zaznaczonyRozmiar tekstu, a nie poprzedni zaznaczonyRozmiar tekstu. Mam nadzieję, że to pomoże!

+0

po otrzymaniu 'UIKeyboardDidShowNotification' jest za późno na rozpoczęcie animacji. Ale tak, w tym momencie pozycja karetki jest zgłaszana poprawnie. –

+0

@deville Tak, ja też wolę opóźnienie, ponieważ od razu podaje poprawną linię prostą. Ale w aplikacji Notatki firmy Apple można zauważyć, że używają one "UIKeyboardDidShowNotification" (używają również automatycznego przewijania UIScrollView, co jest cichym bałaganem), więc uważam, że Apple oznaczało 'UIKeyboardDidShowNotification', aby uzyskać opiekę prostą i że otrzymanie niepoprawnej instrukcji w 'UIKeyboardWillShowNotification' nie jest błędem, chociaż myślę, że powinien to naprawić. – SFF

1

Miałem ten sam problem, ale z UIKeyboardWillShowNotification. Dodanie niewielkiego opóźnienia pomogło w moim przypadku:

func keyboardWillAppear(notification: NSNotification!) { 
    dispatch_after_delay(0.01) {    
     if textView.selectedTextRange { 
      // at this point range is correct 
     } 
    } 
} 

func dispatch_after_delay(delay:NSTimeInterval, queue: dispatch_queue_t = dispatch_get_main_queue(), block: dispatch_block_t) { 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), queue, block) 
}