Câu trả lời:
Cập nhật: Từ ios10,
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;
Từ IOS 7và Sau đó UITextView
có phương thức ủy nhiệm:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*
để chặn các nhấp chuột vào liên kết. Và đây là cách tốt nhất để làm điều đó.
Đối với hệ điều hanh 6và trước đó, một cách hay để làm điều này là bằng cách phân lớp UIApplication
và ghi đè-(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
Bạn sẽ cần phải triển khai openURL:
trong ủy quyền của mình.
Bây giờ, để ứng dụng bắt đầu với lớp con mới của bạn UIApplication
, hãy định vị tệp main.m trong dự án của bạn. Trong tệp nhỏ khởi động ứng dụng của bạn, thường có dòng sau:
int retVal = UIApplicationMain(argc, argv, nil, nil);
Tham số thứ ba là tên lớp cho ứng dụng của bạn. Vì vậy, thay thế dòng này cho:
int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);
Điều này đã làm các mẹo cho tôi.
UIApplication
và thay thế việc triển khai openURL. Mặc dù theo cách này, rất khó (nhưng không phải là không thể) để tham chiếu việc triển khai ban đầu.
Trong iOS 7 trở lên
Bạn có thể sử dụng Phương pháp ủy quyền UITextView sau:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
Chế độ xem văn bản gọi phương thức này nếu người dùng nhấn hoặc nhấn và giữ liên kết URL. Việc thực hiện phương pháp này là tùy chọn. Theo mặc định, chế độ xem văn bản sẽ mở ứng dụng chịu trách nhiệm xử lý loại URL và chuyển URL cho nó. Bạn có thể sử dụng phương pháp này để kích hoạt một hành động thay thế, chẳng hạn như hiển thị nội dung web tại URL trong chế độ xem web trong ứng dụng hiện tại.
Quan trọng:
Các liên kết trong chế độ xem văn bản chỉ tương tác nếu chế độ xem văn bản có thể chọn được nhưng không thể chỉnh sửa. Nghĩa là, nếu giá trị của UITextView thì thuộc tính selectable là CÓ và thuộc tính isEditable là KHÔNG.
UIWebView
nếu bạn muốn thực hiện một số văn bản khác các liên kết và không chính URL đó. Các <a>
thẻ vẫn là cách tốt nhất để đi trong trường hợp đó.
Đối với 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
}
}
hoặc nếu mục tiêu là> = IOS 10
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
Phiên bản Swift:
Thiết lập UITextView tiêu chuẩn của bạn sẽ trông giống như thế này, đừng quên ủy nhiệm và 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)
Sau khi lớp học của bạn kết thúc, hãy thêm phần này:
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
}
}
Với Swift 5 và iOS 12, bạn có thể sử dụng một trong ba mẫu sau để tương tác với các liên kết trong a UITextView
.
UITextView
's dataDetectorTypes
tài sản.Cách đơn giản nhất để tương tác với số điện thoại, url hoặc địa chỉ trong a UITextView
là sử dụng thuộc dataDetectorTypes
tính. Đoạn mã mẫu dưới đây cho biết cách triển khai nó. Với mã này, khi người dùng nhấn vào số điện thoại, một UIAlertController
cửa sổ bật lên.
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
's textView(_:shouldInteractWith:in:interaction:)
phương phápNếu bạn muốn thực hiện một số hành động tùy chỉnh thay vì UIAlertController
bật lên khi nhấn vào một số điện thoại trong khi sử dụng dataDetectorTypes
, bạn phải UIViewController
tuân thủ UITextViewDelegate
giao thức và triển khai textView(_:shouldInteractWith:in:interaction:)
. Đoạn mã dưới đây cho thấy cách triển khai nó:
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
vàNSAttributedString.Key.link
Là một thay thế, bạn có thể sử dụng NSAttributedString
và thiết lập một URL
cho mình NSAttributedString.Key.link
mẫu mã attribute.The dưới đây cho thấy một thi thể của nó. Với mã này, khi người dùng nhấn vào chuỗi phân bổ, một UIAlertController
cửa sổ bật lên.
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
}
}
Swift 4:
1) Tạo lớp sau (UITextView phân lớp):
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) Bất cứ nơi nào bạn thiết lập chế độ xem văn bản của mình, hãy làm như sau:
//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")
}
}
Nếu bạn đang sử dụng bảng phân cảnh, hãy đảm bảo rằng chế độ xem văn bản của bạn trông giống như thế này trong trình kiểm tra danh tính bảng bên phải:
Thì đấy! Bây giờ bạn nhận được liên kết chạm ngay lập tức thay vì khi URL shouldInteractWith phương thức URL
Không chắc chắn bạn sẽ chặn liên kết dữ liệu được phát hiện như thế nào hoặc loại chức năng bạn cần chạy. Nhưng bạn có thể sử dụng phương thức didBeginE Edit TextField để chạy kiểm tra / quét qua trường văn bản nếu bạn biết mình đang tìm kiếm gì..chẳng hạn như so sánh các chuỗi văn bản đáp ứng định dạng ### - ### - ####, hoặc bắt đầu bằng "www." để lấy các trường đó, nhưng bạn sẽ cần viết một đoạn mã nhỏ để dò tìm qua chuỗi trường văn bản, nhận lại những gì bạn cần và sau đó trích xuất nó để sử dụng cho chức năng của bạn. Tôi không nghĩ điều này sẽ khó đến vậy, một khi bạn thu hẹp chính xác những gì bạn muốn và sau đó tập trung vào các bộ lọc câu lệnh if () của bạn xuống thành mẫu đối sánh rất cụ thể về những gì bạn cần.
Điều này ngụ ý rằng người dùng sẽ chạm vào hộp văn bản để kích hoạt didBeginE Chỉnh sửa (). Nếu đó không phải là loại tương tác người dùng mà bạn đang tìm kiếm, bạn có thể chỉ cần sử dụng Bộ hẹn giờ kích hoạt, bắt đầu trên ViewDidAppear () hoặc loại khác dựa trên nhu cầu và chạy qua chuỗi textfields, sau đó chạy qua chuỗi textfield mà bạn đã xây dựng, bạn chỉ cần tắt Bộ hẹn giờ trở lại.
application:handleOpenURL:
được gọi khi một ứng dụng khác mở ứng dụng của bạn bằng cách mở một URL có lược đồ mà ứng dụng của bạn hỗ trợ. Nó không được gọi khi ứng dụng của bạn bắt đầu mở một URL.
Tôi nghĩ rằng cách duy nhất để làm những gì Vladimir muốn là sử dụng UIWebView thay vì UITextView. Làm cho bộ điều khiển chế độ xem của bạn triển khai UIWebViewDelegate, đặt đại biểu của UIWebView thành bộ điều khiển chế độ xem và trong triển khai bộ điều khiển chế độ xem webView:shouldStartLoadWithRequest:navigationType:
để mở [request URL]
trong một chế độ xem thay vì thoát ứng dụng của bạn và mở nó trong Mobile Safari.