NSAttributedStringにクリック可能なリンクを作成するにはどうすればよいですか?


200

でハイパーリンクをクリック可能にするのは簡単UITextViewです。IBのビューで「リンクを検出する」チェックボックスを設定するだけで、HTTPリンクが検出され、ハイパーリンクに変換されます。

ただし、それでもユーザーに表示されるのは「生の」リンクであることを意味します。RTFファイルとHTMLの両方を使用すると、ユーザーが読み取り可能な文字列を、その後ろにリンクを設定できます。

属性付きテキストをテキストビューにインストールするのは簡単です(または、UILabelまたはUITextFieldについては。)。ただし、その属性付きテキストにリンクが含まれている場合は、クリックできません。

ユーザーが読み取れるテキストをUITextViewUILabelまたはでクリック可能にする方法はありUITextFieldますか?

SOではマークアップが異なりますが、一般的な考え方は次のとおりです。私が欲しいのはこのようなテキストです:

このモーフはFace Dancerで生成されました。クリックすると、App Storeで表示されます。

私が得ることができる唯一のものはこれです:

このモーフはFace Dancerで生成されました。アプリストアで表示するには、http://example.com/facedancerをクリックしてください


このサンプルを試してください.. IFTweetLabel Hope it
help


目のウィンクで100Kを超える素晴らしい仕事。100Kクラブへようこそ。まあ当然!
vacawama

@vacawama、待って、いつそれが起こったの?前回見たときは≈98kでした!(10万人のクラブのメンバーとしてSOグッズがもらえるという噂を聞きましたか?)
Duncan C

彼らは質問の賛成票を+5から+10に変更したため、800の賛成票がある場合、すぐに+4000を獲得しました。私はまだ100kの盗品(4月に交差)を待っています。スワッグベンダーの変更について...
vacawama

回答:


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あり、UILabelURLを開くことはサポートしていません。UILabelリンクで使用したい場合は、TTTAttributedLabelを確認できます。

また、クリック時にURLを開くか開くdataDetectorTypesようUITextViewに値を設定する必要があります。または、コメントで提案されているデリゲートメソッドを使用できます。UIDataDetectorTypeLinkUIDataDetectorTypeAll


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
アーメドNawar

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プロジェクトで同じことを行うという要件に達したので、ここに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 2016年

3
@ioop。上記の元の投稿に非常に小さな例を追加しました。
Karl Nosworthy 16

7
これは正しく機能しました。リンクをクリックできるようにするには、UITextViewを選択可能にする必要があると言いたいだけです
lujop

1
@feleciagenet。ObjectiveCとSwiftの両方の実装で、メソッドはブール結果を返し、一致と結果セットが発生したかどうかを示します。あなたが見ているエラーはあなたがその結果をキャプチャしていないためです-これは問題ありません。ローカル変数に割り当てて結果を取得するか、メソッドを調整して必要に応じてブール値を返さないようにすることができます。それが役に立てば幸いですか?
Karl Nosworthy 2017

1
@feleciagenetで問題ありません。メソッドの結果の保存とチェックをSwiftとObjectiveCの両方の例に追加しました。
Karl Nosworthy 2017

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のClick to Face Dancerビューをクリックしてください。ここで私は3つのフェイスダンサーを使用していますが、
うまくいき

1
この場合は、- (void)setLinkForRange:(NSRange)range withLinkHandler:(void(^)(FRHyperLabel *label, NSRange selectedRange))handler; 代わりにAPIを使用してください。githubページのreadmeを参照してください。
Jinghan Wang、2015

1
FRHyperLabelはもう機能していないようです。「characterIndexForPoint:」内では、常に-1(見つかりません)を返します。
John Pang

マルチラインラベルでは機能しません。文字の検出がおかしい。15文字のリンク文字列は一部の最初の文字でのみクリック可能で、他の文字は何もしない
Accid Bright

27

ujellのソリューションのマイナーな改善:NSStringの代わりにNSURLを使用する場合、任意の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リンクがテキストにリンクを設定するためのカテゴリメソッドを作成しました。

-(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はうまくいきません。何であれ、代わりlinkTextAttributesにのUITextViewが適用されます。あなたのNSForegroundColorAttributeNameために働きますか?
ディマ

あなたもlinkTextAttributes同じことに設定していないのですか?それともtintColor?同じテキストビューで2つのリンクを異なる色で表示できますか?
ディマ

1
これが実際のコードNSRange range = [self.text rangeOfString:textToFind options:NSCaseInsensitiveSearch];です。if(range.location!= NSNotFound){NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:self.text]; [string addAttribute:NSLinkAttributeName value:url range:range]; [string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:range]; self.text = @ ""; self.attributedText = string; }
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 2016

13

私の質問の核心は、テキストを操作してリンクを追加するためのカスタムコードを記述しなくても、テキストビュー/フィールド/ラベルにクリック可能なリンクを作成できるようにしたかったことです。データ駆動型にしたかったのです。

私は最終的にそれを行う方法を見つけました。問題は、IBが埋め込みリンクを尊重しないことです。

さらに、iOSバージョンのでNSAttributedStringは、RTFファイルから属性付き文字列を初期化できません。のOS XバージョンにNSAttributedString 、RTFファイルを入力として受け取るイニシャライザがあります。

NSAttributedString NSCodingプロトコルに準拠しているため、NSDataとの間で変換できます。

RTFファイルを入力として受け取り、NSCodingからのNSDataを含む拡張子.dataのファイルを出力するOS Xコマンドラインツールを作成しました。次に、.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 URLUITextFieldDelegateメソッドで必要なアクションを追加できます。

乾杯!!


7

簡単な答えは、UILabelの代わりにUITextViewを使用することです。を有効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ファイルを読み取って、に変換しNSAttributedStringattributedText自分のとして設定しUITextView、ハイパーリンクを使用できました。各ハイパーリンクの範囲を見つけて、属性を使用して設定するのは、大変な作業でした。
Nicolas Miari

6

特定のurl(urlString)の文字列(fullString)にlink(linkString)を追加するメソッドを作成しました。

- (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 2018年

5

私は純粋なUILabelを使い続ける必要があり、これを私のタップ認識機能から呼びました(これは、ここでのマレックスの応答に基づいています: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 16

4

更新:

私の質問には2つの重要な部分がありました:

  1. クリック可能なリンクに表示されるテキストが、呼び出される実際のリンクと異なるリンクを作成する方法:
  2. テキストに属性を設定するためにカスタムコードを使用せずにリンクを設定する方法。

iOS 7が属性付きテキストをからロードする機能を追加したことがわかりましたNSData

UITextViewこの@IBInspectable属性を利用して、RTFファイルからコンテンツを直接IBにロードできるカスタムサブクラスを作成しました。ファイル名をIBに入力するだけで、あとはカスタムクラスが行います。

詳細は次のとおりです。

iOS 7ではNSAttributedString、メソッドを取得しましたinitWithData:options:documentAttributes:error:。このメソッドを使用すると、NSDataオブジェクトからNSAttributedStringをロードできます。最初にRTFファイルをNSData initWithData:options:documentAttributes:error:にロードしてから、を使用してそのNSDataをテキストビューにロードできます。(initWithFileURL:options:documentAttributes:error:属性付き文字列をファイルから直接ロードするメソッドもありますが、そのメソッドはiOS 9でinitWithData:options:documentAttributes:error:廃止されました。廃止されなかったメソッドを使用する方が安全です。

使用しているリンクに固有のコードを作成せずに、クリック可能なリンクをテキストビューにインストールできる方法が必要でした。

私が思いついた解決策は、呼び出すUITextViewのカスタムサブクラスを作成し、それにと呼ばれるプロパティRTF_UITextViewを与えることでした。プロパティに属性を追加すると、Interface Builderは「属性インスペクター」でそのプロパティを公開します。その後、カスタムコードを使用してIBからその値を設定できます。@IBInspectableRTF_Filename@IBInspectable

また@IBDesignable、カスタムクラスに属性を追加しました。この@IBDesignable属性は、カスタムビュークラスの実行中のコピーをInterface Builderにインストールして、ビュー階層のグラフィック表示で確認できるようにすることをXcodeに指示します。()残念ながら、このクラスでは、@IBDesignableプロパティは不安定なようです。最初に追加したときに機能しましたが、テキストビューのプレーンテキストのコンテンツを削除すると、ビュー内のクリック可能なリンクが消えてしまい、元に戻すことができませんでした。)

私のコードRTF_UITextViewは非常に単純です。追加に加えて、@IBDesignable属性とRTF_Filenameを持つプロパティ@IBInspectable属性を、Iを添加didSet()する方法をRTF_Filenameプロパティ。このdidSet()メソッドは、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以外の何かを表示するクリック可能なテキストについて非常に明確にありました。質問を一目見ただけでしたね。
Duncan C

1
他の目的には役立たなかったが、確かにこれは私が探し求めていたものだ...私のチャットアプリケーションのリンクをクリック可能にする方法。ビンゴこの記事を見つけました...ありがとうございます!xcodeがTwitterとハッシュタグの有効化を可能にすることを望みます。
MizAkita 2016年

これは、未加工のリンクを挿入したカスタムテキストでも機能します。Behavior-> Selectable and Detection-> Linksを必ず選択してください。
クルブスク2018年

3

Swiftバージョン:

    // 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を使用して、リンクにdataDetectorTypesを設定します。

このような:

testTextView.editable = false 
testTextView.dataDetectorTypes = .link

リンク、電話番号、住所などを検出したい場合

testTextView.dataDetectorTypes = .all

3
いいえ。これは、リンクをクリック可能にするだけです。私の質問は、「ここをクリック」などの任意のテキストをクリック可能にすることに関するものであり、URLのようなものではありませんhttp://somedomain/someurl?param=value
Duncan C

2

Duncan 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の「編集可能」動作を無効にしてください。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.