iOS 7 UITextView 的原生链接不会取消触摸

Posted

技术标签:

【中文标题】iOS 7 UITextView 的原生链接不会取消触摸【英文标题】:iOS 7 UITextView's native links don't cancel touch 【发布时间】:2014-08-08 14:44:32 【问题描述】:

我想我在 ios 7 的 UITextView 中遇到了一个错误,但我找不到任何关于它的参考或讨论,所以在这里尝试确认我没有遗漏任何东西:

虫子

我有一个 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;

问题是,如果您按下链接,然后尝试拖动以取消触摸:链接的高亮状态消失,但一旦您的手指离开屏幕,代理就会触发。

我无法找到一种方法来告诉 textview 在它应该取消时不要触发,或者检测它应该已经取消。

我确信这是一个错误,因为视觉按下/取消状态和动作触发不匹配。

【问题讨论】:

【参考方案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;

【讨论】:

以上是关于iOS 7 UITextView 的原生链接不会取消触摸的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 7 上成为第一响应者后,UITextView 不会滚动到插入符号

iOS 7 + Calabash:带有 NSLinkAttributeName 的 UITextView 和链接上的可访问性不起作用

在 ios 8 中的 UITextview 中单击时,键盘不会弹出但在 ios 7 中运行良好

iOS 给UITextView加一个placeholder

UITextView iOS 7的行数

UITextView contentInset 在 iOS 7 上的 UITextView 中不起作用?