ユーザーがUITextViewで自動検出された電話リンクをタッチしたときにカスタムアクションを実行することは可能ですか?代わりにUIWebViewを使用することはお勧めしません。
そして、Appleクラス参照からのテキストを繰り返すだけではありません-すでに読んでいます。
ありがとう。
更新: ios1 から、
_- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;
_
ios7 以降およびUITextView
にはデリゲートメソッドがあります。
_- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*
_
リンクへのクリックをインターセプトします。そして、これはそれを行う最良の方法です。
ios6 以前の場合、UIApplication
をサブクラス化し、-(BOOL)openURL:(NSURL *)url
を上書きすることにより、これを行うことができます。
_@interface MyApplication : UIApplication {
}
@end
@implementation MyApplication
-(BOOL)openURL:(NSURL *)url{
if ([self.delegate openURL:url])
return YES;
else
return [super openURL:url];
}
@end
_
デリゲートに_openURL:
_を実装する必要があります。
ここで、アプリケーションをUIApplication
の新しいサブクラスで開始するには、プロジェクトでファイルmain.mを見つけます。アプリをブートストラップするこの小さなファイルには、通常次の行があります。
_int retVal = UIApplicationMain(argc, argv, nil, nil);
_
3番目のパラメーターは、アプリケーションのクラス名です。したがって、この行を次のように置き換えます。
_int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);
_
これは私のためにトリックをしました。
IOS 7以降
次のUITextViewデリゲートメソッドを使用できます。
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
ユーザーがURLリンクをタップまたは長押しすると、テキストビューがこのメソッドを呼び出します。このメソッドの実装はオプションです。デフォルトでは、テキストビューはURLタイプを処理するアプリケーションを開き、URLを渡します。このメソッドを使用して、現在のアプリケーション内のWebビューのURLでWebコンテンツを表示するなど、代替アクションをトリガーできます。
重要:
テキストビューのリンクは、テキストビューが選択可能であるが編集できない場合にのみインタラクティブです。つまり、UITextViewの値が選択可能なプロパティの場合はYESで、isEditableプロパティはNOです。
Swift 3
textView.delegate = self
extension MyTextView: UITextViewDelegate
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
GCITracking.sharedInstance.track(externalLink: URL)
return true
}
}
またはターゲットが> = IOS 10の場合
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
Swiftバージョン:
標準のUITextViewセットアップは次のようになります。デリゲートとdataDetectorTypesを忘れないでください。
var textView = UITextView(x: 10, y: 10, width: CardWidth - 20, height: placeholderHeight) //This is my custom initializer
textView.text = "dsfadsaf www.google.com"
textView.selectable = true
textView.dataDetectorTypes = UIDataDetectorTypes.Link
textView.delegate = self
addSubview(textView)
クラスが終了したら、このピースを追加します。
class myVC: UIViewController {
//viewdidload and other stuff here
}
extension MainCard: UITextViewDelegate {
func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
//Do your stuff over here
var webViewController = SVModalWebViewController(URL: URL)
view.presentViewController(webViewController, animated: true, completion: nil)
return false
}
}
Swift 5およびiOS 12では、UITextView
内のリンクと対話するために、次の3つのパターンのいずれかを使用できます。
UITextView
の dataDetectorTypes
プロパティを使用します。UITextView
で電話番号、URL、またはアドレスを操作する最も簡単な方法は、dataDetectorTypes
プロパティを使用することです。以下のサンプルコードは、その実装方法を示しています。このコードでは、ユーザーが電話番号をタップすると、UIAlertController
がポップアップします。
_import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView()
textView.text = "Phone number: +33687654321"
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.dataDetectorTypes = [.phoneNumber]
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
}
_
UITextViewDelegate
の textView(_:shouldInteractWith:in:interaction:)
メソッドを使用するUIAlertController
を使用中に電話番号をタップしたときにdataDetectorTypes
をポップアップする代わりにカスタムアクションを実行する場合は、UIViewController
をUITextViewDelegate
プロトコルに準拠させ、textView(_:shouldInteractWith:in:interaction:)
を実装する必要があります。以下のコードは、それを実装する方法を示しています。
_import UIKit
class ViewController: UIViewController, UITextViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView()
textView.delegate = self
textView.text = "Phone number: +33687654321"
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.dataDetectorTypes = [.phoneNumber]
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
/* perform your own custom actions here */
print(URL) // prints: "tel:+33687654321"
return false // return true if you also want UIAlertController to pop up
}
}
_
NSAttributedString
および_NSAttributedString.Key.link
_の使用別の方法として、NSAttributedString
を使用して、その_NSAttributedString.Key.link
_属性にURL
を設定できます。以下のサンプルコードは、その実装例を示しています。このコードでは、ユーザーが属性付き文字列をタップすると、UIAlertController
がポップアップします。
_import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let attributedString = NSMutableAttributedString(string: "Contact: ")
let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works
let attributes = [NSAttributedString.Key.link: phoneUrl]
let phoneAttributedString = NSAttributedString(string: "phone number", attributes: attributes)
attributedString.append(phoneAttributedString)
let textView = UITextView()
textView.attributedText = attributedString
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
}
_
テキストビューに動的コンテンツがあり、リンクが含まれている場合があります。 shouldInteractWithURLが呼び出されるのは、ユーザーがリンクを長押しし、リンクのタップを呼び出していない場合のみです。メンバーに参照がある場合はリダイレクトしてください。
以下は、コードの一部です。
UITextView *ltextView = [[UITextView alloc] init];
[ltextView setScrollEnabled:YES];
[ltextView setDataDetectorTypes:UIDataDetectorTypeLink];
ltextView.selectable = YES;
[ltextView setEditable:NO];
ltextView.userInteractionEnabled = YES;
ltextView.delegate = (id)self;
ltextView.delaysContentTouches = NO;
[self.view addsubview:ltextview];
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange{
[self.mActionDelegate userClickedOnImageLinkFromWebview:URL];
NSLog(@"urls is :- %@",URL);
return FALSE;
}
上記のデリゲートメソッドはタップで呼び出されません。
よろしく、ロヒト・ジャンカル
application:handleOpenURL:
は、別のアプリが開くときに呼び出されますyourアプリがサポートするスキームでURLを開くことによって。アプリがURLを開くときに呼び出されることはありません。
Vladimirが望んでいることを行う唯一の方法は、UITextViewではなくUIWebViewを使用することだと思います。 View ControllerでUIWebViewDelegateを実装し、UIWebViewのデリゲートをView Controllerに設定し、View Controllerでアプリを終了してMobile Safariで開くのではなく、ビューでwebView:shouldStartLoadWithRequest:navigationType:
を開くために[request URL]
を実装します。
私はそれを試していませんが、application:handleOpenURL:
アプリケーションデリゲートのメソッド-すべてのopenURL
リクエストがこのコールバックを通過するように見えます。
検出されたデータリンクをどのようにインターセプトするか、または実行する必要がある機能のタイプがわからない。しかし、探しているものがわかっている場合は、didBeginEditing TextFieldメソッドを使用して、テスト/スキャンをテキストフィールドで実行できる場合があります。たとえば、###-###-####形式に一致するテキスト文字列を比較したり、または「www」で始まりますこれらのフィールドを取得するには、テキストフィールドの文字列をスニッフィングするための小さなコードを作成し、必要なものを調整してから、関数の使用のために抽出する必要があります。必要なものを正確に絞り込み、if()ステートメントフィルターを必要なものの非常に具体的な一致パターンに絞り込んだら、これはそれほど難しいとは思いません。
当然のことですが、これはユーザーがdidBeginEditing()をアクティブにするためにテキストボックスをタッチすることを意味します。それがあなたが探していたユーザーインタラクションのタイプではない場合、ViewDidAppear()または必要に応じて開始し、テキストフィールド文字列を実行し、最後にテキストフィールド文字列を実行するトリガータイマーを使用できます構築したメソッドは、タイマーをオフに戻すだけです。
スウィフト4:
1)次のクラス(サブクラス化されたUITextView)を作成します。
import Foundation
protocol QuickDetectLinkTextViewDelegate: class {
func tappedLink()
}
class QuickDetectLinkTextView: UITextView {
var linkDetectDelegate: QuickDetectLinkTextViewDelegate?
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let glyphIndex: Int? = layoutManager.glyphIndex(for: point, in: textContainer, fractionOfDistanceThroughGlyph: nil)
let index: Int? = layoutManager.characterIndexForGlyph(at: glyphIndex ?? 0)
if let characterIndex = index {
if characterIndex < textStorage.length {
if textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) != nil {
linkDetectDelegate?.tappedLink()
return self
}
}
}
return nil
}
}
2)テキストビューを設定する場合はいつでも、これを行います:
//init, viewDidLoad, etc
textView.linkDetectDelegate = self
//outlet
@IBOutlet weak var textView: QuickDetectLinkTextView!
//change ClassName to your class
extension ClassName: QuickDetectLinkTextViewDelegate {
func tappedLink() {
print("Tapped link, do something")
}
}
ストーリーボードを使用している場合は、右ペインのIDインスペクターでテキストビューが次のようになっていることを確認してください。
ボイラ!これで、URL shouldInteractWith URLメソッドの代わりに、すぐにリンクタップを取得できます