iOS 7 UITextView的本机链接不会取消触摸

时间:2014-08-08 14:44:33

标签: ios7 uitextview uitextviewdelegate datadetectortypes

我想我在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 个答案:

答案 0 :(得分:0)

解决方法(可怕的可怕的侵入性工作)

我通过继承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;
}