Answers:
更新:从 ios10,
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;
从 IOS 7后来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);
第三个参数是您的应用程序的类名。因此,将以下行替换为:
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 5和iOS 12,您可以使用以下三种模式之一来与中的链接进行交互UITextView
。
UITextView
的dataDetectorTypes
属性。与中的电话号码,网址或地址进行交互的最简单方法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
}
}
迅捷版:
您的标准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
}
}
斯威夫特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)无论您在何处设置textview,都应执行以下操作:
//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")
}
}
如果您使用情节提要,请确保右窗格身份检查器中的textview如下所示:
瞧!现在您将立即获得链接点击,而不是当URL shouldInteractWith URL方法时
不确定如何截获检测到的数据链接,或者需要运行哪种类型的函数。但是,如果您知道要查找的内容,则可以使用didBeginEditing TextField方法对文本字段进行测试/扫描。例如,比较符合###-###-####格式的文本字符串,或以“ www。”开头 捕获这些字段,但是您需要编写一些代码来嗅探textfields字符串,重新整理所需的内容,然后将其提取出来以供函数使用。我不认为这会那么困难,一旦您精确地缩小了想要的范围,然后将if()语句集中到所需的非常特定的匹配模式上。
当然,这意味着用户将要触摸文本框以激活didBeginEditing()。如果这不是您要查找的用户交互类型,则可以只使用触发计时器,该触发计时器根据需要从ViewDidAppear()或其他开始,并贯穿文本字段字符串,然后结束时贯穿文本字段字符串您建立的方法,只需关闭计时器。
application:handleOpenURL:
当另一个应用通过使用您的应用支持的方案打开URL来打开您的应用时调用。当您的应用开始打开URL时,不会调用它。
我认为做弗拉基米尔想要的唯一方法是使用UIWebView而不是UITextView。使您的视图控制器实现UIWebViewDelegate,将UIWebView的委托设置为视图控制器,并在视图控制器实现中在视图webView:shouldStartLoadWithRequest:navigationType:
中打开[request URL]
,而不是退出应用程序并在Mobile Safari中打开它。