如何在NSAttributedString中创建可点击的链接?


200

使超链接在 UITextView。您只需在IB中的视图上设置“检测链接”复选框,它就会检测HTTP链接并将其转换为超链接。

但是,这仍然意味着用户看到的是“原始”链接。RTF文件和HTML都允许您设置带有链接“其后”的用户可读字符串。

它易于安装属性文本到文本视图(或UILabelUITextField为此事。)但是,当归于文本包含一个链接,就无法点击。

有没有一种方法,使一个用户可读文本点击UITextViewUILabel还是UITextField

SO上的标记是不同的,但这是一般的想法。我想要的是这样的文字:

此变形是使用Face Dancer生成的,单击可在App Store中查看。

我唯一能得到的是:

此变体是使用Face Dancer生成的,请单击http://example.com/facedancer在应用商店中查看。


试试这个样本.. IFTweetLabel希望它有助于..
Vidhyanand


眨眼间就超过了10万的好工作。欢迎来到100K俱乐部。应得的!
vacawama

@vacawama,等等,什么时候发生的?上次看时,我的≈98k!(我听说有传言说您作为100k俱乐部的一员会有一些赃物吗?)
Duncan C

他们将对问题的投票从+5更改为+10,因此,如果您有800个投票,则可以在瞬间获得+4000。我仍在等待10万赃物(四月越过)。关于改变赃物供应商的事情……
vacawama

Answers:


156

使用NSMutableAttributedString

NSMutableAttributedString * str = [[NSMutableAttributedString alloc] initWithString:@"Google"];
[str addAttribute: NSLinkAttributeName value: @"http://www.google.com" range: NSMakeRange(0, str.length)];
yourTextView.attributedText = str;

编辑

这不是直接有关的问题,但我只想澄清,UITextField并且UILabel不支持打开的URL。如果要UILabel与链接一起使用,则可以检查TTTAttributedLabel

此外,您还应在单击时设置to的dataDetectorTypes值或打开URL。或者,您可以使用注释中建议的委托方法。UITextViewUIDataDetectorTypeLinkUIDataDetectorTypeAll


7
是的,它正在工作,只需将其放在UITextView中并重写委托方法:-(BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)url inRange:(NSRange)characterRange
Yunus Nedim Mehel

这在UILabel中不起作用-当您点击该字段时,什么也不会发生。
Jack BeNimble 2015年

7
@saboehnke您的意思是单击链接时调用方法吗?如果是这样,则实现委托方法,给虚拟url作为属性,并在- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
ujell

2
我不知道它是如何工作的。属性的值应为的类型NSURL。----[str addAttribute: NSLinkAttributeName value: [NSURL URLWithString:@"http://www.google.com"] range: NSMakeRange(0, str.length)];
Nirav Dangi 2015年

1
@NiravDangi来自NSAttributedString.h UIKIT_EXTERN NSString * const NSLinkAttributeName NS_AVAILABLE(10_0, 7_0); // NSURL (preferred) or NSString
艾哈迈德·

142

我发现这确实很有用,但是我需要在很多地方进行操作,因此我将方法打包为以下内容的简单扩展NSMutableAttributedString

迅捷3

extension NSMutableAttributedString {

    public func setAsLink(textToFind:String, linkURL:String) -> Bool {

        let foundRange = self.mutableString.range(of: textToFind)
        if foundRange.location != NSNotFound {
            self.addAttribute(.link, value: linkURL, range: foundRange)
            return true
        }
        return false
    }
}

迅捷2

import Foundation

extension NSMutableAttributedString {

   public func setAsLink(textToFind:String, linkURL:String) -> Bool {

       let foundRange = self.mutableString.rangeOfString(textToFind)
       if foundRange.location != NSNotFound {
           self.addAttribute(NSLinkAttributeName, value: linkURL, range: foundRange)
           return true
       }
       return false
   }
}

用法示例:

let attributedString = NSMutableAttributedString(string:"I love stackoverflow!")
let linkWasSet = attributedString.setAsLink("stackoverflow", linkURL: "http://stackoverflow.com")

if linkWasSet {
    // adjust more attributedString properties
}

物镜

我刚刚达到了在纯Objective-C项目中执行相同操作的要求,所以这里是Objective-C类别。

@interface NSMutableAttributedString (SetAsLinkSupport)

- (BOOL)setAsLink:(NSString*)textToFind linkURL:(NSString*)linkURL;

@end


@implementation NSMutableAttributedString (SetAsLinkSupport)

- (BOOL)setAsLink:(NSString*)textToFind linkURL:(NSString*)linkURL {

     NSRange foundRange = [self.mutableString rangeOfString:textToFind];
     if (foundRange.location != NSNotFound) {
         [self addAttribute:NSLinkAttributeName value:linkURL range:foundRange];
         return YES;
     }
     return NO;
}

@end

用法示例:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:"I love stackoverflow!"];

BOOL linkWasSet = [attributedString setAsLink:@"stackoverflow" linkURL:@"http://stackoverflow.com"];

if (linkWasSet) {
    // adjust more attributedString properties
}

确保将NSTextField的Behavior属性设置为Selectable。 Xcode NSTextField行为属性


一个快速的用法/实现示例将不胜感激。
ioopl

3
@ioop。我在上面的原始帖子中添加了一个非常小的示例,希望对您有所帮助。
卡诺斯沃西

7
这正常工作。只是想说,您需要选择UITextView才能允许链接被点击
lujop

1
@felecia Genet,在Objective C和Swift实现中,该方法都返回一个布尔结果,以指示是否发生匹配和结果集。您看到的错误是因为您没有捕获该结果-很好。您可以通过将结果分配给局部变量来捕获结果,也可以调整方法以使其停止返回布尔值(如果更适合您的需要)。我希望有帮助吗?
卡诺斯沃西

1
@feleciagenet没问题,我在Swift和ObjectiveC示例中都添加了对方法结果的存储和检查。
卡诺斯沃西

34

我刚刚创建了UILabel的子类来专门解决此类用例。您可以轻松添加多个链接,并为它们定义不同的处理程序。当您按下以获取触摸反馈时,它还支持突出显示按下的链接。请参考https://github.com/null09264/FRHyperLabel

就您而言,代码可能像这样:

FRHyperLabel *label = [FRHyperLabel new];

NSString *string = @"This morph was generated with Face Dancer, Click to view in the app store.";
NSDictionary *attributes = @{NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]};

label.attributedText = [[NSAttributedString alloc]initWithString:string attributes:attributes];

[label setLinkForSubstring:@"Face Dancer" withLinkHandler:^(FRHyperLabel *label, NSString *substring){
    [[UIApplication sharedApplication] openURL:aURL];
}];

示例屏幕截图(在这种情况下,处理程序设置为弹出警报,而不是打开URL)

面舞者


如果假设我的文本是这样的,则此变形是使用Face Dancer生成的,请在应用商店Face Dancer中单击“面对Face Dancer”视图。在这里,我有3个Face Dancer,但无法正常工作
MANCHIKANTI KRISHNAKISHORE 2015年

1
在这种情况下,请改用API - (void)setLinkForRange:(NSRange)range withLinkHandler:(void(^)(FRHyperLabel *label, NSRange selectedRange))handler; 。请参考github页面中的自述文件。
王敬翰

1
FRHyperLabel似乎不再起作用。在“ characterIndexForPoint:”内部,它始终返回-1(未找到)。

多行标签不适用于我。字符检测错误。15个字符的链接字符串仅可在某些第一个字符上单击,其他字符则
不起作用

27

ujell解决方案的较小改进:如果使用NSURL而不是NSString,则可以使用任何URL(例如,自定义URL)

NSURL *URL = [NSURL URLWithString: @"whatsapp://app"];
NSMutableAttributedString * str = [[NSMutableAttributedString alloc] initWithString:@"start Whatsapp"];
[str addAttribute: NSLinkAttributeName value:URL range: NSMakeRange(0, str.length)];
yourTextField.attributedText = str;

玩得开心!


21

斯威夫特4:

var string = "Google"
var attributedString = NSMutableAttributedString(string: string, attributes:[NSAttributedStringKey.link: URL(string: "http://www.google.com")!])

yourTextView.attributedText = attributedString

Swift 3.1:

var string = "Google"
var attributedString = NSMutableAttributedString(string: string, attributes:[NSLinkAttributeName: URL(string: "http://www.google.com")!])

yourTextView.attributedText = attributedString

此答案按原样完美运行。似乎不需要其他答案使用的任何着色或自定义子类。
zeroimpl

19

我也有类似的要求,最初我使用UILabel,然后我意识到UITextView更好。我通过禁用交互和滚动使UITextView表现得像UILabel,并制作了用于NSMutableAttributedString设置链接到文本的类别方法,该方法与Karl所做的相同(为此为+1),这是我的obj c版本

-(void)setTextAsLink:(NSString*) textToFind withLinkURL:(NSString*) url
{
    NSRange range = [self.mutableString rangeOfString:textToFind options:NSCaseInsensitiveSearch];

    if (range.location != NSNotFound) {

        [self addAttribute:NSLinkAttributeName value:url range:range];
        [self addAttribute:NSForegroundColorAttributeName value:[UIColor URLColor] range:range];
    }
}

您可以使用下面的委托来处理操作

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)url inRange:(NSRange)characterRange
{
    // do the task
    return YES;
}

1
据我所知NSForegroundColorAttributeName,在NSLinkAttributeName应用范围内设置无效。无论怎样,在linkTextAttributesUITextView,系统就会应用。NSForegroundColorAttributeName对你有用吗?
Dima 2015年

您确定您还没有设置linkTextAttributes相同的东西吗?还是tintColor?您能否使2个链接在同一textview中以不同的颜色显示?
Dima 2015年

1
这是一个工作代码NSRange range = [self.text rangeOfString:textToFind options:NSCaseInsensitiveSearch]; 如果(range.location!= NSNotFound){NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:self.text]; [string addAttribute:NSLinkAttributeName value:url range:range]; [string addAttribute:NSForegroundColorAttributeName值:[UIColor blueColor] range:range]; self.text = @“”; self.attributedText =字符串; }
Nosov Pavel 2015年

16

使用UITextView,它支持可单击的链接。使用以下代码创建属性字符串

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:strSomeTextWithLinks];

然后如下设置UITextView文本

NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor redColor],

                                 NSUnderlineColorAttributeName: [UIColor blueColor],

                                 NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};

customTextView.linkTextAttributes = linkAttributes; // customizes the appearance of links
textView.attributedText = attributedString;

确保在XIB中启用UITextView的“可选”行为。


15
我认为这是最好的解决方案!关于启用的注意事项Selectable很重要!
LunaCodeGirl 2015年

这没有为我强调链接(iOS 7、8)。我需要使用NSUnderlineStyleAttributeName:[NSNumber numberWithInt:NSUnderlineStyleSingle]
prewett

1
使其成为可选的是最重要且非直观的信息!
Nicolas Massart

13

我的问题的核心是我希望能够在文本视图/字段/标签中创建可点击的链接,而不必编写自定义代码来操纵文本并添加链接。我希望它是数据驱动的。

我终于想出了办法。问题在于IB不支持嵌入式链接。

此外,iOS版本的NSAttributedString不允许您从RTF文件初始化属性字符串。的OS X版本NSAttributedString 确实具有将RTF文件作为输入的初始化程序。

NSAttributedString 符合NSCoding协议,因此您可以将其转换为NSData

我创建了一个OS X命令行工具,该工具使用RTF文件作为输入,并输出扩展名为.data的文件,该文件包含来自NSCoding的NSData。然后,将.data文件放入我的项目中,并添加几行代码,将文本加载到视图中。代码看起来像这样(该项目在Swift中):

/*
If we can load a file called "Dates.data" from the bundle and convert it to an attributed string,
install it in the dates field. The contents contain clickable links with custom URLS to select
each date.
*/
if
  let datesPath = NSBundle.mainBundle().pathForResource("Dates", ofType: "data"),
  let datesString = NSKeyedUnarchiver.unarchiveObjectWithFile(datesPath) as? NSAttributedString
{
  datesField.attributedText = datesString
}

对于使用大量格式化文本的应用程序,我创建了一个构建规则,该规则告诉Xcode特定文件夹中的所有.rtf文件都是源文件,而.data文件是输出文件。完成此操作后,我只需将.rtf文件添加到指定目录中(或编辑现有文件),然后构建过程就可以确定它们是新的/已更新,运行命令行工具,然后将这些文件复制到应用程序捆绑包中。它工作得很漂亮。

我写了一篇博客文章,链接到一个演示该技术的示例(Swift)项目。你可以在这里看到它:

在可在您的应用中打开的UITextField中创建可点击的URL


11

Swift 3示例,用于检测归因于文本点击的动作

https://stackoverflow.com/a/44226491/5516830

let termsAndConditionsURL = TERMS_CONDITIONS_URL;
let privacyURL            = PRIVACY_URL;

override func viewDidLoad() {
    super.viewDidLoad()

    self.txtView.delegate = self
    let str = "By continuing, you accept the Terms of use and Privacy policy"
    let attributedString = NSMutableAttributedString(string: str)
    var foundRange = attributedString.mutableString.range(of: "Terms of use") //mention the parts of the attributed text you want to tap and get an custom action
    attributedString.addAttribute(NSLinkAttributeName, value: termsAndConditionsURL, range: foundRange)
    foundRange = attributedString.mutableString.range(of: "Privacy policy")
    attributedString.addAttribute(NSLinkAttributeName, value: privacyURL, range: foundRange)
    txtView.attributedText = attributedString
}

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "WebView") as! SKWebViewController

    if (URL.absoluteString == termsAndConditionsURL) {
        vc.strWebURL = TERMS_CONDITIONS_URL
        self.navigationController?.pushViewController(vc, animated: true)
    } else if (URL.absoluteString == privacyURL) {
        vc.strWebURL = PRIVACY_URL
        self.navigationController?.pushViewController(vc, animated: true)
    }
    return false
}

明智的做法是,您可以添加所需的任何操作 shouldInteractWith URL UITextFieldDelegate方法。

干杯!!


7

快速答案是使用UITextView代替UILabel。您需要启用Selectable和禁用Editable

然后禁用滚动指示器并反弹。

屏幕截图

屏幕截图

我的解决方案使用NSMutableAttributedStringHTML字符串NSHTMLTextDocumentType

NSString *s = @"<p><a href='https://itunes.apple.com/us/app/xxxx/xxxx?mt=8'>https://itunes.apple.com/us/app/xxxx/xxxx?mt=8</a></p>";

NSMutableAttributedString *text = [[NSMutableAttributedString alloc]
                                           initWithData: [s dataUsingEncoding:NSUnicodeStringEncoding]
                                           options: @{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType }
                                           documentAttributes: nil
                                           error: nil
                                           ];

cell.content.attributedText = text;

这个。我能够从资源包中读取RTF文件,将其转换为NSAttributedString,将其设置为attributedText我的UITextView,超级链接才起作用!找到每个超链接的范围并使用属性进行设置将需要很多工作。
Nicolas Miari

6

我已经编写了一种方法,该方法将link(linkString)添加到具有特定url(urlString)的字符串(fullString):

- (NSAttributedString *)linkedStringFromFullString:(NSString *)fullString withLinkString:(NSString *)linkString andUrlString:(NSString *)urlString
{
    NSRange range = [fullString rangeOfString:linkString options:NSLiteralSearch];
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:fullString];

    NSMutableParagraphStyle *paragraphStyle = NSMutableParagraphStyle.new;
    paragraphStyle.alignment = NSTextAlignmentCenter;
    NSDictionary *attributes = @{NSForegroundColorAttributeName:RGB(0x999999),
                                 NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Light" size:10],
                                 NSParagraphStyleAttributeName:paragraphStyle};
    [str addAttributes:attributes range:NSMakeRange(0, [str length])];
    [str addAttribute: NSLinkAttributeName value:urlString range:range];

    return str;
}

您应该这样称呼它:

NSString *fullString = @"A man who bought the Google.com domain name for $12 and owned it for about a minute has been rewarded by Google for uncovering the flaw.";
NSString *linkString = @"Google.com";
NSString *urlString = @"http://www.google.com";

_youTextView.attributedText = [self linkedStringFromFullString:fullString withLinkString:linkString andUrlString:urlString];

它是可单击的,但不会打开链接或其他任何内容。它只是像一个按钮一样单击,不会执行任何操作。
Reza.Ab

5

我需要继续使用纯UILabel,从我的水龙头识别器中调用它(这是基于malex在这里的响应:UILabel的接触点处的字符索引

UILabel* label = (UILabel*)gesture.view;
CGPoint tapLocation = [gesture locationInView:label];

// create attributed string with paragraph style from label

NSMutableAttributedString* attr = [label.attributedText mutableCopy];
NSMutableParagraphStyle* paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.alignment = label.textAlignment;

[attr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, label.attributedText.length)];

// init text storage

NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attr];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];

// init text container

NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(label.frame.size.width, label.frame.size.height+100) ];
textContainer.lineFragmentPadding  = 0;
textContainer.maximumNumberOfLines = label.numberOfLines;
textContainer.lineBreakMode        = label.lineBreakMode;

[layoutManager addTextContainer:textContainer];

// find tapped character

NSUInteger characterIndex = [layoutManager characterIndexForPoint:tapLocation
                                                  inTextContainer:textContainer
                         fractionOfDistanceBetweenInsertionPoints:NULL];

// process link at tapped character

[attr enumerateAttributesInRange:NSMakeRange(characterIndex, 1)
                                         options:0
                                      usingBlock:^(NSDictionary<NSString *,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
                                          if (attrs[NSLinkAttributeName]) {
                                              NSString* urlString = attrs[NSLinkAttributeName];
                                              NSURL* url = [NSURL URLWithString:urlString];
                                              [[UIApplication sharedApplication] openURL:url];
                                          }
                                      }];

这非常有帮助,我无法从最后一行的字符中获取索引。初始化CGSize时,您的代码在textContainer上的值为+100,这对我来说意义不大,但确实可以解决。
blueether

4

更新:

我的问题有两个关键部分:

  1. 如何制作一个链接,其中可点击链接显示的文本与所调用的实际链接不同:
  2. 如何设置链接而不必使用自定义代码来设置文本的属性。

事实证明,iOS 7添加了从中加载属性文本的功能NSData

我创建了一个UITextView利用该@IBInspectable属性的自定义子类,并允许您直接在IB中从RTF文件加载内容。您只需在IB中键入文件名,其余的由定制类完成。

详细信息如下:

在iOS 7中,NSAttributedString获得了方法initWithData:options:documentAttributes:error:。该方法使您可以从NSData对象加载NSAttributedString。您可以先将RTF文件加载到NSData中,然后使用initWithData:options:documentAttributes:error:将该NSData加载到文本视图中。(请注意,还有一种方法initWithFileURL:options:documentAttributes:error:可以直接从文件中加载属性字符串,但是该方法在iOS 9中已被弃用。使用不被弃用的method更为安全initWithData:options:documentAttributes:error:

我想要一种方法,使我可以将可点击的链接安装到我的文本视图中,而不必创建特定于我正在使用的链接的代码。

我想到的解决方案是创建一个我调用的UITextView的自定义子类,RTF_UITextView并为其提供一个@IBInspectable名为的属性RTF_Filename。将@IBInspectable属性添加到属性会使Interface Builder在“ Attributes Inspector”中公开该属性。然后,您可以从IB定制代码中设置该值。

我还向@IBDesignable自定义类添加了一个属性。该@IBDesignable属性告诉Xcode,它应该将自定义视图类的运行副本安装到“界面”构建器中,以便您可以在视图层次结构的图形显示中看到它。()不幸的是,对于此类,该@IBDesignable属性似乎是片状的。当我第一次添加它时它就起作用了,但是后来我删除了文本视图的纯文本内容,并且视图中的可单击链接消失了,无法将它们找回来。)

我的代码RTF_UITextView非常简单。除了添加@IBDesignable属性和带有RTF_Filename属性的@IBInspectable属性外,我还向属性添加了一种didSet()方法RTF_FilenamedidSet()只要RTF_Filename属性值更改,该方法就会被调用。该didSet()方法的代码非常简单:

@IBDesignable
class RTF_UITextView: UITextView
{
  @IBInspectable
  var RTF_Filename: String?
    {
    didSet(newValue)
    {
      //If the RTF_Filename is nil or the empty string, don't do anything
      if ((RTF_Filename ?? "").isEmpty)
      {
        return
      }
      //Use optional binding to try to get an URL to the
      //specified filename in the app bundle. If that succeeds, try to load
      //NSData from the file.
      if let fileURL = NSBundle.mainBundle().URLForResource(RTF_Filename, withExtension: "rtf"),
        
        //If the fileURL loads, also try to load NSData from the URL.
        let theData = NSData(contentsOfURL: fileURL)
      {
        var aString:NSAttributedString
        do
        {
          //Try to load an NSAttributedString from the data
          try
            aString = NSAttributedString(data: theData,
              options: [:],
              documentAttributes:  nil
          )
          //If it succeeds, install the attributed string into the field.
          self.attributedText = aString;
        }
        catch
        {
          print("Nerp.");
        }
      }
      
    }
  }
}

请注意,如果@IBDesignable属性无法可靠地允许您在“界面”构建器中预览样式化的文本,则最好将上述代码设置为UITextView的扩展,而不是自定义子类。这样,您可以在任何文本视图中使用它,而不必将文本视图更改为自定义类。

如果您需要支持iOS 7之前的iOS版本,请参阅我的其他答案。

您可以从gitHub下载包含此新类的示例项目:

Github上的DatesInSwift演示项目


3

只需找到UITextView的无代码解决方案: 在此处输入图片说明

启用检测->链接选项,URL和电子邮件也将被检测并单击!


3
这使得链接可点击。我希望用户可读的文本后面带有链接。参见我原始问题中的示例。
Duncan C

是的,我的回答仅适用于链接与文本相同的情况。如果链接是其他内容,我将遵循@ujell的回答。
比尔·陈

3
我的问题非常具体,是有关显示除URL之外的其他内容的可点击文本。您只看了一眼这个问题,对吗?
邓肯C

1
并没有达到其他目的,但可以肯定的是,这正是我要寻找的东西……一种使我的聊天应用程序中的链接可点击的方法。宾果游戏我发现了这篇文章...谢谢!希望xcode允许启用twitter和hash标签。
MizAkita '16

即使使用由原始链接插入的自定义文本,此功能也可以使用。记住选择行为->可选和检测->链接。
krlbsk

3

迅捷版:

    // Attributed String for Label
    let plainText = "Apkia"
    let styledText = NSMutableAttributedString(string: plainText)
    // Set Attribuets for Color, HyperLink and Font Size
    let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(14.0), NSLinkAttributeName:NSURL(string: "http://apkia.com/")!, NSForegroundColorAttributeName: UIColor.blueColor()]
    styledText.setAttributes(attributes, range: NSMakeRange(0, plainText.characters.count))
    registerLabel.attributedText = styledText

3

使用UITextView并为Link设置dataDetectorTypes。

像这样:

testTextView.editable = false 
testTextView.dataDetectorTypes = .link

如果要检测链接,电话号码,地址等,则

testTextView.dataDetectorTypes = .all

3
不可以。这仅使您可以单击链接。我的问题是特定于使诸如“单击此处”之类的任意文本可点击,而不是使URL像http://somedomain/someurl?param=value
Duncan C

2

快速补充了邓肯C对IB行为的原始描述。他写道:“在UITextView中使超链接可单击很简单。您只需在IB中的视图上设置“检测链接”复选框,它就会检测到HTTP链接并将其转换为超链接。”

我的经验(至少在xcode 7中)是,您还必须取消“可编辑”行为,才能检测到可点击的URL。


2

如果您对@Karl Nosworthy和@esilver上面提供的内容有疑问,我已将NSMutableAttributedString扩展更新为其Swift 4版本。

extension NSMutableAttributedString {

public func setAsLink(textToFind:String, linkURL:String) -> Bool {

    let foundRange = self.mutableString.range(of: textToFind)
    if foundRange.location != NSNotFound {
         _ = NSMutableAttributedString(string: textToFind)
        // Set Attribuets for Color, HyperLink and Font Size
        let attributes = [NSFontAttributeName: UIFont.bodyFont(.regular, shouldResize: true), NSLinkAttributeName:NSURL(string: linkURL)!, NSForegroundColorAttributeName: UIColor.blue]

        self.setAttributes(attributes, range: foundRange)
        return true
    }
    return false
  }
}


0

如果要在UITextView中使用NSLinkAttributeName,则可以考虑使用AttributedTextView库。这是一个UITextView子类,使处理它们非常容易。有关更多信息,请参见: https //github.com/evermeer/AttributedTextView

您可以像这样使文本的任何部分进行交互(其中textView1是UITextView IBoutlet):

textView1.attributer =
    "1. ".red
    .append("This is the first test. ").green
    .append("Click on ").black
    .append("evict.nl").makeInteract { _ in
        UIApplication.shared.open(URL(string: "http://evict.nl")!, options: [:], completionHandler: { completed in })
    }.underline
    .append(" for testing links. ").black
    .append("Next test").underline.makeInteract { _ in
        print("NEXT")
    }
    .all.font(UIFont(name: "SourceSansPro-Regular", size: 16))
    .setLinkColor(UIColor.purple) 

为了处理主题标签和提及,您可以使用如下代码:

textView1.attributer = "@test: What #hashtags do we have in @evermeer #AtributedTextView library"
    .matchHashtags.underline
    .matchMentions
    .makeInteract { link in
        UIApplication.shared.open(URL(string: "https://twitter.com\(link.replacingOccurrences(of: "@", with: ""))")!, options: [:], completionHandler: { completed in })
    }


0
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:strSomeTextWithLinks];

NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor redColor],   
                                 NSUnderlineColorAttributeName: [UIColor blueColor],
                                 NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};

customTextView.linkTextAttributes = linkAttributes; // customizes the appearance of links
textView.attributedText = attributedString;

关键点:

  • 确保在XIB中启用UITextView的“可选”行为。
  • 确保禁用XIB中UITextView的“可编辑”行为。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.