web-dev-qa-db-ja.com

UITextViewリンクタップの認識が遅れる

IOS 7アプリで、リンクが含まれているUITextViewがありますが、リンクをタップしても起動しません。扱いにくい「タップアンドホールド」にしか反応しません。 UIWebViewリンクタップの動作のように、ユーザーがタップするとすぐに応答するようにします。これが私のセットアップです:

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."];
    [text addAttribute:NSLinkAttributeName value:@"myurl://tapped" range:NSMakeRange(6, 16)];

    self.textView.attributedText = text;
    self.textView.editable = NO;
    self.textView.delaysContentTouches = NO;
}

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
{
    if ([[URL scheme] isEqualToString:@"myurl"])
    {
        // Handle tap

        return NO;
    }

    return YES;
}

Apple shouldInteractWithURLメソッドのドキュメントには、「ユーザーがURLリンクをタップまたは長押しすると、テキストビューがこのメソッドを呼び出す」と記載されています。長押しは機能していますが、タップが機能しないようです。

これをすぐに応答させる方法を誰かが知っていますか?

35
lehn0058

UITextViewは選択可能ですか?試してみてください:

self.textView.selectable = YES;

編集:

Appleの発言に反して、長押しがそれを実行する唯一の方法であると考え始めています。これを確認してください link 、おそらく役立つでしょう。

14
nnarayann

それでもネイティブUITextViewを使いたい場合は、タップ認識機能をテキストビューに追加して、タップ位置で文字列属性を取得できます。リンクを見つけたら、すぐに開くことができます。

私はiOS 7/8でこれを解決するGistを書きました。これはUITextViewの軽量拡張であり、-[UITextViewDelegate textView:shouldInteractWithURL:inRange:]も転送し、内部のタップジェスチャー認識機能を公開します。

https://Gist.github.com/benjaminbojko/c92ac19fe4db3302bd28

ここに簡単な例があります:以下の例はiOS 8でのみ機能します。iOS7 + 8のサポートについては、上記の要旨を参照してください。

タップ認識機能を追加します。

// ...

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedTextView:)];
[myTextView addGestureRecognizer:tapRecognizer];
myTextView.selectable = YES; // otherwise the gesture won't recognize

// ...

そして、コールバックを追加します。

- (void)tappedTextView:(UITapGestureRecognizer *)tapGesture {
    if (tapGesture.state != UIGestureRecognizerStateEnded) {
        return;
    }

    UITextView *textView = (UITextView *)tapGesture.view;
    CGPoint tapLocation = [tapGesture locationInView:textView];
    UITextPosition *textPosition = [textView closestPositionToPoint:tapLocation];
    NSDictionary *attributes = [textView textStylingAtPosition:textPosition inDirection:UITextStorageDirectionForward];

    NSURL *url = attributes[NSLinkAttributeName];

    if (url) {
        [[UIApplication sharedApplication] openURL:url];
    }
}

そしてSwift version:

認識機能をタップ:

let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("tappedTextView:"))
myTextView.addGestureRecognizer(tapRecognizer)
myTextView.selectable = true

折り返し電話:

func tappedTextView(tapGesture: UIGestureRecognizer) {

        let textView = tapGesture.view as! UITextView
        let tapLocation = tapGesture.locationInView(textView)
        let textPosition = textView.closestPositionToPoint(tapLocation)
        let attr: NSDictionary = textView.textStylingAtPosition(textPosition, inDirection: UITextStorageDirection.Forward)

        if let url: NSURL = attr[NSLinkAttributeName] as? NSURL {
            UIApplication.sharedApplication().openURL(url)
        }

        }
38
Benjamin Bojko

Nnarayannが述べたように、 CCHLinkTextView はタップ認識の遅延の問題を回避します。このライブラリは独自のジェスチャ認識機能を実装しており、バージョン1.0で利用可能になりました。

7
Claus

Swift 4ソリューション


  • タップジェスチャー認識機能を使用してリンクを処理します
  • isSelectabletrueでもfalseでも、機能します

let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleLinkTap(_:)))
textView.addGestureRecognizer(tapRecognizer)

@objc func handleLinkTap(_ recognizer: UITapGestureRecognizer) {
    let tapLocation = recognizer.location(in: textView)
    guard
        let textPosition = textView.closestPosition(to: tapLocation),
        let url = textView.textStyling(at: textPosition, in: .forward)?[NSAttributedStringKey.link.rawValue],
        let urlString = (url as? String) ?? (url as? URL)?.absoluteString,
        urlString == "myurl"
    else { return }

    let url = URL(string: urlString)!
    // Do whatever you want with this URL, such as
    UIApplication.shared.openURL(url)
}
3
AamirR

場合によっては、iOSシミュレータでは機能しないか、長押しした場合にのみ機能することがあります。

実際のデバイスでテストする必要があります。

そして、それをselectableに設定することを忘れないでください。

2
Laszlo

設定してみましたかtextview.delaysContentTouches = NO;?多分それは助けることができます。

1
dezinezync

他のテキストが表示されているなど、UITextViewを使用する差し迫った理由がない場合は、UILabelUITapGestureRecognizerと組み合わせて使用​​して効果を得ることができますあなたが探しています。

それ以外の場合は、実際のUIWebViewを代わりに使用できます。

1
dandan78