Собственные ссылки iOS 7 UITextView не отменяют касание

Я думаю, что столкнулся с ошибкой в ​​UITextView в iOS 7, но я не смог найти ссылку на нее или обсуждение, поэтому пытаюсь подтвердить здесь, что я ничего не упустил:

Ошибка

У меня есть настройка UITextView следующим образом:

UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 100, 280, 140)];
textView.editable = NO;
textView.dataDetectorTypes = UIDataDetectorTypeLink;
textView.backgroundColor = [UIColor lightGrayColor];
textView.delegate = self;
textView.text = [NSString stringWithFormat:@"This is a UITextView in a UIViewController. It has editable %d, selectable %d, dataDectorTypes %d (UIDataDetectorTypeLink), and a link! http://www.google.com.\n\nIf you click the link, it works normally. If you press, then drag your finger away to cancel the touch, the highlight goes away but the action still fires. Shouldn't the action not fire?", textView.editable, textView.selectable, textView.dataDetectorTypes];
[self.view addSubview:textView];

Текст textview содержит ссылку, которая, если щелкнуть, работает как положено: она обращается к делегату, который просто выводит предупреждение:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange{

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"You clicked the link!" message:@"You clicked the link. Maybe you tried to move away to cancel the touch, but you clicked it anyway." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alertView show];
    return NO;
}

Проблема заключается в том, что если вы нажмете ссылку, а затем попытаетесь перетащить ее, чтобы отменить касание: состояние выделения ссылки исчезнет, ​​но делегат сработает, как только ваш палец покинет экран.

Я не смог найти способ сказать текстовому просмотру, чтобы он не срабатывал, когда он должен был быть отменен, или обнаружить, что он должен был быть отменен.

Я убежден, что это ошибка, потому что визуальное состояние нажатия/отмены и срабатывание действия не совпадают.


person Michelle Ellis    schedule 08.08.2014    source источник


Ответы (1)


Обходной путь (ужасно ужасный инвазивный обходной путь)

Я обошел это, создав подкласс UIApplication для отслеживания всех касаний экрана. Удерживая местоположение последнего касания, я могу в делегате сопоставить местоположение со ссылкой, чтобы определить, следует ли считать его действительным:

MyCustomApplication.m

@implementation MyCustomApplication

static CGPoint lastTouchVar;

- (void)sendEvent:(UIEvent *)event {
    if (event.type == UIEventTypeTouches) {
        lastTouchVar = [((UITouch*)event.allTouches.anyObject) locationInView:[[[UIApplication sharedApplication] delegate] window]];
    }
    [super sendEvent:event];
}

+ (CGPoint)lastTouch {
    return lastTouchVar;
}

@end

(используйте его в main.m)

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, @"MyCustomApplication", NSStringFromClass([MyAppDelegate class]));
    }
}

И сопоставьте это...

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {

    CGPoint lastTouchWRTTextView = [[[[UIApplication sharedApplication] delegate] window] convertPoint:[MyCustomApplication lastTouch] toView:textView];

    lastTouchWRTTextView.x -= textView.textContainerInset.left;
    lastTouchWRTTextView.y -= textView.textContainerInset.top;

    if (CGRectContainsPoint(CGRectMake(0, 0, textView.frame.size.width, textView.frame.size.height), lastTouchWRTTextView)) {

        int characterIndexForPoint = [textView.textContainer.layoutManager characterIndexForPoint:lastTouchWRTTextView inTextContainer:textView.textContainer fractionOfDistanceBetweenInsertionPoints:nil];
        if (NSLocationInRange(characterIndexForPoint, characterRange)) {
            // It's a real tap! Do something!
        }
    }
    return NO;
}
person Michelle Ellis    schedule 08.08.2014