回答:
更新:から iOS10、
- (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);
これは私にとってはトリックでした。
UIApplication
、openURL実装を分類して置き換えることもできます。この方法でも、元の実装を参照するのは難しい(ただし不可能ではない)。
iOS 7以降
次のUITextViewデリゲートメソッドを使用できます。
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
ユーザーがURLリンクをタップまたは長押しすると、テキストビューはこのメソッドを呼び出します。このメソッドの実装はオプションです。デフォルトでは、テキストビューはURLタイプを処理するアプリケーションを開き、URLを渡します。このメソッドを使用して、現在のアプリケーション内のWebビューのURLにWebコンテンツを表示するなど、代替アクションをトリガーできます。
重要:
テキストビューのリンクは、テキストビューが選択可能で編集不可の場合にのみインタラクティブです。つまり、UITextViewの値の場合、selectableプロパティはYESで、isEditableプロパティはNOです。
UIWebView
あなたには、いくつかの他のテキストにしたい場合は、リンクではなくURL自体を。タグはまだその場合に行くための最良の方法です。<a>
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では、次の3つのパターンのいずれかを使用して、のリンクを操作できますUITextView
。
UITextView
のdataDetectorTypes
プロパティを使用します。で電話番号、URL、またはアドレスを操作する最も簡単な方法UITextView
は、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
して設定することができます。以下のサンプルコードは、可能な実装を示しています。このコードでは、ユーザーが属性付き文字列をタップすると、ポップアップが表示されます。URL
NSAttributedString.Key.link
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
}
}
スウィフト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メソッドの代わりに、すぐにリンクタップを取得できます
検出されたデータリンクをどのようにインターセプトするか、または実行する必要がある関数のタイプが不明です。しかし、didBeginEditing TextFieldメソッドを利用して、探しているものがわかっている場合は、テキストフィールド全体をテスト/スキャンできます。たとえば、###-###-####形式を満たすテキスト文字列を比較したり、または「www」で始まる。これらのフィールドを取得するには、textfields文字列をスニッフィングし、必要なものを再調整して、関数で使用するために抽出するための小さなコードを書く必要があります。私はこれがそれほど難しいとは思わない、一度あなたがそれが望むものを正確に絞り込み、そしてあなたのif()ステートメントがあなたが必要とするものの非常に特定のマッチングパターンにフィルターを絞ったならば。
これは、ユーザーがdidBeginEditing()をアクティブにするためにテキストボックスに触れることを意味します。それがあなたが探していたユーザーインタラクションのタイプではない場合、ViewDidAppear()または必要に応じて開始されるトリガーTimerを使用して、テキストフィールド文字列を実行し、最後にテキストフィールド文字列を実行することができます作成したメソッドでは、単にタイマーをオフに戻します。
application:handleOpenURL:
アプリがサポートするスキームを含むURLを開いて別のアプリがアプリを開くと呼び出されます。アプリがURLを開き始めるときに呼び出されません。
私はウラジミールが望むことをする唯一の方法はUITextViewの代わりにUIWebViewを使うことだと思います。ビューコントローラーにUIWebViewDelegateを実装させ、UIWebViewのデリゲートをビューコントローラーに設定し、ビューコントローラーの実装で、アプリを終了してMobile SafariでwebView:shouldStartLoadWithRequest:navigationType:
開くの[request URL]
ではなく、ビューで開くようにします。