iOS 7中UITextView链接检测

59

我有一个通过Interface Builder管理的UITextView。在数据检测方面,我已经勾选了“链接”。在iOS 6中,一切都正常工作,链接被突出显示并且可以点击。然而,在iOS 7中,所有链接仍然只是普通文本。可编辑和可选择的复选框未被勾选。

可能需要注意的是,UITextView是容器视图的子视图,该容器视图再次位于UIScrollView中。


https://dev59.com/cXNA5IYBdhLWcg3wWseK#37745157 - Kuldeep Singh
17个回答

70

看起来在iOS 7中,只有当可选中UITextView时链接检测才能正常工作。因此,使我的UITextView不可选会停止链接检测的工作。

我还在iOS 6中测试过这一点,并确认在iOS 6中,即使UITextView不可选择,链接检测也能正常工作。


在iOS7.0.2和Xcode5上,当我通过storyboard检查UITextView上的可选和链接时,链接检测可以正常工作。然而,当我将textview设置在tableview上的UITableViewCell上,并快速滚动时,它会崩溃并显示“Terminating app due to uncaught exception 'NSRangeException',reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'”。我发现,如果我在storyboard上不勾选链接检测,则不会发生崩溃。 - Umeumeume
我也发现,除非我通过编程设置字体大小,否则在Storyboard上通过UITextView进行链接检测会出错。很奇怪... - Umeumeume
同样适用于iOS8(.1)。 更糟糕的是:如果我选择不可编辑、不可选择和电话号码检测,则应用程序将立即崩溃。 有没有办法进行电话号码检测,如果未检测到电话号码,则不允许选择内容? - Christian

32

今天在电话号码检测时遇到了一些问题。似乎UITextView在我设置新文本后,仍然保留旧的电话号码并将文本保持高亮显示。

我发现,在设置新字符串文本之前先setText:nil,可以重置textview,并使电话号码正常高亮显示。我想知道这是否是iOS 7.0中UITextView的某种bug。

不管怎样,这对我来说确实起作用了。


4
感谢您的回复,但不幸的是那并没有解决问题。 - Tobias
这对我也起作用了。我遇到了一个问题,文本包含URL和电话号码,整个文本块变成了一个链接,指向文本末尾的电话号码。首先将文本属性设置为nil解决了我的问题。谢谢! - Jason Barker
3
具有讽刺意味的是,我在另一个我正在构建的应用程序中再次遇到了这个问题。在prepareForReuse方法中将textview设置为可编辑,然后立即取消编辑似乎比将文本设置为nil更有效。 - Theo Bendixson
将文本设置为nil对我很有用。我有一个消息表,当我插入消息时,会检查字符串中的标签。如果有标签,我会使用attributedText。问题是,如果前一个消息已经将标签突出显示为蓝色,在加载更多消息时,其他消息也会变成蓝色,即使它们没有标签。非常好的建议! - denikov
3
将textView设置为nil,或者切换可编辑性似乎都不能解决我的问题。 - Trespassers W
非常感谢你,这个修复方案如此简单,我真为之前没有想到而自责! - IfElseTryCatch

26

iOS7首次推出时,这个问题困扰了我,我在这个帖子中找到了答案(在设置实际值之前将UITextView的文本属性设置为nil就可以解决)。 然后突然间,这个问题又出现了(对我来说,整个字符串都被突出显示为链接),可能是由于iOS更新引起的。

最终让我成功的方法是停止使用文本属性,而是设置attributedText。 一旦我这样做了,编程设置字体/滚动/可选择/可编辑等等的需要就消失了。 我在IB中定义了我的UITextView,并按照所需设置了值(不可滚动、不可编辑、可选择、检测链接和电话号码),然后构建了一个属性字符串并设置:

myUITextView.attributedString = myAttributedString;

突然间,一切都正常工作了。希望这能对其他人有所帮助。


2
这是唯一对我有效的解决方案。截至7.0.4,其他解决方案似乎都不再起作用了。 - aepryus
太棒了!这正是我所需要的 - 所有其他解决方案都不起作用?但这个可以。谢谢! - Andy
添加我的发现,这在7.1版本中似乎也适用。非常感谢您找出了这个问题的解决方法。 - christopherdrum
这应该被视为正确答案,因为Missaq说它是没有黑客的那个。 - Magoo
在8.3上对我有效,但是我无法设置文本颜色。属性文本中的ForegroundColor被忽略了。 - Alex Sorokoletov
显示剩余2条评论

18

我有同样的问题,禁用UITextView上的滚动会在加载时激活链接检测,而不仅仅是当用户与文本视图交互后才能工作。UITextView还必须是可选择和不可编辑的。

detailTextView.scrollEnabled = NO;
detailTextView.editable = NO;
detailTextView.selectable = YES;

在iOS6中,可选择性或启用滚动并不是必要的。

另一个需要检查的问题是单元格及其内容视图上是否启用了用户交互,否则链接将无法点击。


3
滚动提示很完美,谢谢!要完全修复,请将此与文本= nil结合使用,它就可以正常工作了! - N V
取消勾选滚动启用解决了我的问题。谢谢! - Yariv Nissim
同意@NV的观点。在这3个语句之前添加text = nil即可完美解决!谢谢 - mikemike396

16

UITableView单元格中使用数据检测器属性,必须添加以下这些行到textview

    txtvwMsgText.userInteractionEnabled = YES;
    txtvwMsgText.dataDetectorTypes = UIDataDetectorTypeLink;
    txtvwMsgText.scrollEnabled = NO;
    txtvwMsgText.editable = NO;
    txtvwMsgText.selectable = YES;

8

您应该查看NSDataDetector

您可以使用它来查找和处理不同的数据(链接、电话号码等)。请在此网站上查看:

http://nshipster.com/nsdatadetector/

您还可以使用UITextView的dataDetectorTypes属性来设置您想要在代码中检测的内容。对于您来说,可能只是一个故事板转换问题。
textView.dataDetectorTypes = UIDataDetectorTypeLink;

4
谢谢您的回答,但在iOS 6中,UITextView可以在Interface Builder中设置正确的检测器而无需额外编码就能实现此功能。那么为什么在iOS 7中这样做不再起作用了呢? - Tobias
这就是为什么我想知道是否存在IB问题。你可能更新到使用Xcode 5中的新storyboard了吗? - Daniel
不,我从项目开始就使用了故事板,尽管在此期间我从Xcode 4更新到Xcode 5。 - Tobias
如果您将子类中的文本视图替换为标准视图,那么它是否按预期工作? - Daniel
不好意思,没有成功。我也尝试了你建议的代码示例来设置检测器类型,但是没有成功。 - Tobias

7

请注意,您的textview仅在不可编辑时才能识别链接!

这是一个关于如何制作带有`link detection`的可编辑UITextView的不错教程。

带有链接检测的可编辑UITextView

至今为止我没有遇到任何问题。

这个技巧是使用一个手势识别器GestureRecognizer来转发触摸并启用/禁用编辑。

您可以将同样的方法应用于上的可选/不可选问题。


6

经过几次测试,我找到了解决方案。

如果您希望链接处于活动状态,并且不希望选择启用,则需要编辑gestureRecognizers。

例如-有3个LongPressGestureRecognizers。 其中一个用于单击链接(minimumPressDuration = 0.12),第二个用于可编辑模式下的缩放(minimumPressDuration = 0.5),第三个用于选择(minimumPressDuration = 0.8)。 这个解决方案删除了选择和编辑模式下的第二个长按手势识别器。

NSArray *textViewGestureRecognizers = self.captionTextView.gestureRecognizers;
NSMutableArray *mutableArrayOfGestureRecognizers = [[NSMutableArray alloc] init];
for (UIGestureRecognizer *gestureRecognizer in textViewGestureRecognizers) {
    if (![gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
        [mutableArrayOfGestureRecognizers addObject:gestureRecognizer];
    } else {
        UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)gestureRecognizer;
        if (longPressGestureRecognizer.minimumPressDuration < 0.3) {
            [mutableArrayOfGestureRecognizers addObject:gestureRecognizer];
        }
    }
}
self.captionTextView.gestureRecognizers = mutableArrayOfGestureRecognizers;

已在iOS 9上测试,但应该适用于所有版本(iOS 7、8、9)。 希望能对您有所帮助!:)


4

使用UITextView来实现启用、可选、不可滚动和可检测链接并不像看起来那么简单。我在iOS 8中遇到了这个问题。所以我的解决方案是在viewDidLoad中做类似以下的操作,然后当文本框编辑完成时将editable属性设置为NO(通常会有一个像doneIsTapped的方法)。关键在于在完成对textview的文本值设置后将editable属性设置为NO。这将使UITextview中的链接生效。

- (void)viewDidLoad 
{
    [super viewDidLoad];
    self.txtViewComment.editable = YES;
    self.txtViewComment.selectable = YES;
    self.txtViewComment.dataDetectorTypes = UIDataDetectorTypeLink;
    self.txtViewComment.scrollEnabled = NO;
}

并且。
- (IBAction)doneIsTapped:(id)sender 
{
    self.txtViewComment.text = @"set text what ever you want";
    self.txtViewComment.editable = NO; 
}

这样可以使链接在TextView中可用。此外,我建议暂时不要使用故事板(或者在Apple修复此问题之前)只使用代码来避免任何不必要的混乱。希望这能有所帮助。


4

我找到了诀窍,这在iOS 7中有效!

您需要在xib或编程方式中设置UITextView可选择。

self.yourTextView.selectable = YES;

然后您需要禁用滚动条,设置文本后再重新启用滚动条。

self.yourTextView.scrollEnabled = NO;
[self.yourTextView setText:contentString];
self.yourTextView.scrollEnabled = YES;

3
我不知道这是否真正解决了问题,或者只是通过将某个东西塞进另一个东西中我修好了那个东西。 - Ethan Mick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接