NSAttributedString에서 클릭 가능한 링크를 만들려면 어떻게해야합니까?


200

에서 하이퍼 링크를 클릭 할 수있게 만드는 것은 쉽지 않습니다 UITextView. IB의보기에서 "링크 감지"확인란을 설정하면 HTTP 링크가 감지되어 하이퍼 링크로 바뀝니다.

그러나 이것은 여전히 ​​사용자가 보는 것이 "원시"링크라는 것을 의미합니다. RTF 파일과 HTML 모두 "뒤에"링크가있는 사용자가 읽을 수있는 문자열을 설정할 수 있습니다.

중요한 텍스트를 텍스트보기 (또는 a UILabel또는) 로 쉽게 설치할 수 있습니다 UITextField. 그러나 해당 텍스트에 링크가 포함되어 있으면 클릭 할 수 없습니다.

사용자가 읽을 수있는 텍스트 A의 클릭 할 수있는 방법이 있나요 UITextView, UILabel또는 UITextField?

마크 업은 SO와 다르지만 일반적인 아이디어는 다음과 같습니다. 내가 원하는 것은 다음과 같은 텍스트입니다.

이 모프는 Face Dancer 로 생성되었습니다 . 클릭하면 앱 스토어에서 볼 수 있습니다.

내가 얻을 수있는 유일한 것은 이것입니다.

이 모프는 Face Dancer로 생성되었습니다 . 앱 스토어에서 보려면 http://example.com/facedancer 를 클릭하십시오 .


이 샘플을 시도 .. IFTweetLabel 희망이 도움이 ...
Vidhyanand


눈의 윙크에서 100K 이상을 날리는 좋은 직업. 100K 클럽에 오신 것을 환영합니다. 잘 마땅하다!
vacawama

@vacawama, 잠깐, 언제 그런 일이 있었습니까? 내가 마지막으로 보았을 때 나는 98k에 있었다! (100k 클럽의 일원으로서 SO swag을 얻는다는 소문이 있습니까?)
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 을 확인할 수 있습니다 .

또한 당신은 설정해야합니다 dataDetectorTypes당신의 가치 UITextViewUIDataDetectorTypeLink또는 UIDataDetectorTypeAll클릭하면 열려있는 URL로. 또는 의견에서 제안한대로 위임 방법을 사용할 수 있습니다.


7
예, 작동하고 있습니다. 간단히 UITextView에 넣고 대리자 메서드를 재정의하십시오.-(BOOL) textView : (UITextView *) textView shouldInteractWithURL : (NSURL *) url inRange : (NSRange) characterRange
Yunus Nedim Mehel

UILabel에서는 작동하지 않습니다. 필드를 탭해도 아무 변화가 없습니다.
Jack BeNimble

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

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
}

목표 -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

3
@ioop. 위의 원래 게시물에 아주 작은 예를 추가했습니다. 도움이 되길 바랍니다.
Karl Nosworthy

7
이것은 올바르게 작동했습니다. 링크를 클릭 할 수 있도록 UITextView를 선택 가능해야한다고 말하고 싶습니다
lujop

1
@felecia genet, Objective C 및 Swift 구현에서이 메소드는 부울 결과를 반환하여 일치 및 결과 집합이 발생했는지 여부를 나타냅니다. 당신이보고있는 오류는 그 결과를 캡처하지 않기 때문에 발생합니다. 결과를 로컬 변수에 할당하여 결과를 캡처하거나 필요에 따라 부울 값을 반환하지 않도록 메소드를 조정할 수 있습니다. 도움이 되길 바랍니다.
Karl Nosworthy

1
@ feleciagenet 문제 없음, Swift 및 ObjectiveC 예제 모두에 메소드 결과 저장 및 검사를 추가했습니다.
Karl Nosworthy

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 명의 얼굴 댄서를 가지고있다
MANCHIKANTI KRISHNAKISHORE

1
이 경우 - (void)setLinkForRange:(NSRange)range withLinkHandler:(void(^)(FRHyperLabel *label, NSRange selectedRange))handler; 대신 API를 사용하십시오 . github 페이지의 readme를 참조하십시오.
Jinghan Wang

1
FRHyperLabel이 더 이상 작동하지 않는 것 같습니다. "characterIndexForPoint :"내부에서는 항상 -1 (찾을 수 없음)을 반환합니다.
존 팡

여러 줄 레이블에 대해 작동하지 않습니다. 문자 감지가 잘못되었습니다. 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

스위프트 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처럼 작동하게 만들고 NSMutableAttributedStringKarl이 수행 한 것과 동일한 텍스트로 링크를 설정 하는 범주 메서드를 만들었 습니다 (+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

linkTextAttributes같은 것으로 설정하지 않습니까? 아니면 tintColor? 동일한 텍스트보기에서 2 개의 링크를 다른 색상으로 표시 할 수 있습니까?
Dima

1
다음은 작업 코드입니다. NSRange range = [self.text rangeOfString : textToFind 옵션 : NSCaseInsensitiveSearch]; if (range.location! = NSNotFound) {NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString : self.text]; [문자열 addAttribute : NSLinkAttributeName 값 : URL 범위 : 범위]; [문자열 addAttribute : NSForegroundColorAttributeName 값 : [UIColor blueColor] 범위 : 범위]; self.text = @ ""; self.attributedText = 문자열; }
Nosov Pavel

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

이것은 저에게 링크를 강조하지 않았습니다 (iOS 7, 8). [NSUnderlineStyleSingle의 NSNumber numberWithInt :] 나는 NSUnderlineStyleAttributeName 사용하는 데 필요한
prewett

1
선택 가능하게하는 것이 가장 중요하고 직관적이지 않은 정보입니다!
Nicolas Massart

13

내 질문의 핵심은 텍스트를 조작하고 링크를 추가하기 위해 사용자 정의 코드를 작성하지 않고도 텍스트보기 / 필드 / 레이블에서 클릭 가능한 링크를 만들 수 있기를 원한다는 것입니다. 나는 그것이 데이터 중심적이기를 원했습니다.

나는 그것을하는 방법을 마침내 알아 냈습니다. 문제는 IB가 포함 된 링크를 존중하지 않는다는 것입니다.

또한 iOS 버전의 NSAttributedStringRTF 파일에서 속성 문자열을 초기화 할 수 없습니다. OS X 버전 에는 RTF 파일을 입력으로 사용하는 이니셜 라이저 NSAttributedString 있습니다.

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
}

많은 형식의 텍스트를 사용하는 앱의 경우 지정된 폴더의 모든 .rtf 파일이 소스이고 .data 파일이 출력임을 Xcode에 알려주는 빌드 규칙을 만듭니다. 일단 그렇게하면 .rtf 파일을 지정된 디렉토리에 추가하거나 기존 파일을 편집하면 빌드 프로세스에서 새로운 / 업데이트되고 명령 줄 도구를 실행하고 파일을 앱 번들에 복사합니다. 아름답게 작동합니다.

이 기술을 보여주는 샘플 (Swift) 프로젝트로 연결되는 블로그 게시물을 작성했습니다. 여기에서 볼 수 있습니다 :

앱에서 열리는 UITextField에서 클릭 가능한 URL 만들기


11

중요한 텍스트 탭에서 동작을 감지하는 스위프트 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

빠른 답변은 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 파일을 읽을로 변환 할 수 있었다 NSAttributedString의로 설정 attributedText내의 UITextView와 하이퍼 링크 단지 작품! 각 하이퍼 링크의 범위를 찾고 속성을 사용하여 설정하려면 많은 작업이 필요했을 것입니다.
Nicolas Miari

6

특정 URL (urlString)을 사용하여 링크 (linkString)를 문자열 (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속성을 RTB 파일의 컨텐츠를 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:이상 사용되지 않습니다. 더 이상 사용되지 않는 method를 사용하는 것이 더 안전합니다 .

사용중인 링크에 특정한 코드를 만들지 않고도 텍스트보기에 클릭 가능한 링크를 설치할 수있는 방법을 원했습니다.

내가 생각해 낸 해결책은 내가 호출하는 UITextView의 사용자 정의 하위 클래스를 만들고 라는 속성을 RTF_UITextView제공하는 것이 었습니다 . 속성에 속성을 추가 하면 인터페이스 빌더가 해당 속성을 "속성 관리자"에 노출시킵니다. 그런 다음 사용자 정의 코드를 사용하여 IB에서 해당 값을 설정할 수 있습니다.@IBInspectableRTF_Filename@IBInspectable

또한 @IBDesignable사용자 정의 클래스에 속성을 추가했습니다 . 이 @IBDesignable속성은 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의 답변을 따르십시오.
Bill Chan

3
내 질문은 URL 이외의 것을 표시하는 클릭 가능한 텍스트에 관한 것입니다. 당신은 그 질문을 한 눈에 보지 않았습니까?
Duncan C

1
다른 목적을 제공하지는 않았지만 분명히 이것은 내가 찾은 것입니다 ... 채팅 응용 프로그램의 링크를 클릭 가능하게 만드는 방법입니다. 빙고이 기사를 찾았습니다 ... 감사합니다! Wish xcode는 트위터 및 해시 태그 활성화를 허용합니다.
MizAkita

이것은 원시 링크에 삽입 된 사용자 정의 텍스트에서도 작동합니다. 동작-> 선택 가능 및 감지-> 링크를 선택해야합니다.
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를 사용하고 링크에 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.