เป็นไปได้หรือไม่ที่จะดำเนินการแบบกำหนดเองเมื่อผู้ใช้แตะลิงก์โทรศัพท์ที่ตรวจจับอัตโนมัติใน UITextView โปรดอย่าแนะนำให้ใช้ UIWebView แทน
และโปรดอย่าทำซ้ำข้อความจากการอ้างอิงคลาสของ apple - แน่นอนฉันได้อ่านแล้ว
ขอบคุณ.
เป็นไปได้หรือไม่ที่จะดำเนินการแบบกำหนดเองเมื่อผู้ใช้แตะลิงก์โทรศัพท์ที่ตรวจจับอัตโนมัติใน UITextView โปรดอย่าแนะนำให้ใช้ UIWebView แทน
และโปรดอย่าทำซ้ำข้อความจากการอ้างอิงคลาสของ apple - แน่นอนฉันได้อ่านแล้ว
ขอบคุณ.
คำตอบ:
ปรับปรุง: จาก 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 นั้น คุณสามารถใช้วิธีนี้เพื่อทริกเกอร์การดำเนินการอื่นเช่นการแสดงเนื้อหาเว็บที่ URL ในมุมมองเว็บภายในแอปพลิเคชันปัจจุบัน
สิ่งสำคัญ:
ลิงก์ในมุมมองข้อความเป็นแบบโต้ตอบได้ก็ต่อเมื่อเลือกมุมมองข้อความได้ แต่แก้ไขไม่ได้ นั่นคือถ้าค่าของ UITextView คุณสมบัติที่เลือกได้คือ 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
สถานที่ให้บริการวิธีที่ง่ายที่สุดในการโต้ตอบกับหมายเลขโทรศัพท์ URL หรือที่อยู่ใน a 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
's 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
}
}
เวอร์ชัน 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 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")
}
}
หากคุณใช้สตอรีบอร์ดตรวจสอบให้แน่ใจว่ามุมมองข้อความของคุณมีลักษณะเช่นนี้ในตัวตรวจสอบข้อมูลประจำตัวของบานหน้าต่างด้านขวา:
โวลา! ตอนนี้คุณจะได้รับลิงค์แตะทันทีแทนที่จะเป็นเมื่อ URL shouldInteractWith URL วิธี
ฉันยังไม่ได้ลองใช้ตัวเอง แต่คุณสามารถลองใช้application:handleOpenURL:
วิธีการในตัวแทนแอปพลิเคชันของคุณได้ดูเหมือนว่าopenURL
คำขอทั้งหมดจะผ่านการติดต่อกลับนี้
ไม่แน่ใจว่าคุณจะสกัดกั้นการเชื่อมโยงข้อมูลที่ตรวจพบได้อย่างไรหรือฟังก์ชันประเภทใดที่คุณต้องเรียกใช้ แต่คุณอาจสามารถใช้เมธอด didBeginEditing TextField เพื่อเรียกใช้การทดสอบ / สแกนผ่านฟิลด์ข้อความหากคุณรู้ว่ากำลังมองหาอะไร.. เช่นการเปรียบเทียบสตริงข้อความที่ตรงตามรูปแบบ ### - ### - #### หรือขึ้นต้นด้วย "www." เพื่อคว้าฟิลด์เหล่านั้น แต่คุณจะต้องเขียนโค้ดเล็กน้อยเพื่อสูดดมผ่านสตริงฟิลด์ข้อความกำหนดสิ่งที่คุณต้องการใหม่จากนั้นแยกออกมาเพื่อใช้งานฟังก์ชันของคุณ ฉันไม่คิดว่ามันจะยากขนาดนั้นเมื่อคุณ จำกัด สิ่งที่คุณต้องการให้แคบลงอย่างแน่นอนจากนั้นจึงเน้นคำสั่ง if () ของคุณกรองลงไปตามรูปแบบการจับคู่ที่เฉพาะเจาะจงมากสำหรับสิ่งที่คุณต้องการ
จาก couse หมายความว่าผู้ใช้จะแตะกล่องข้อความเพื่อเปิดใช้งาน didBeginEditing () หากนั่นไม่ใช่ประเภทของการโต้ตอบกับผู้ใช้ที่คุณกำลังมองหาคุณสามารถใช้ตัวจับเวลาทริกเกอร์ที่เริ่มต้นใน ViewDidAppear () หรืออื่น ๆ ตามความต้องการและทำงานผ่านสตริงฟิลด์ข้อความจากนั้นในตอนท้ายของคุณจะเรียกใช้สตริงฟิลด์ข้อความ วิธีการที่คุณสร้างขึ้นคุณเพียงแค่ปิดตัวจับเวลา
application:handleOpenURL:
เรียกว่าเมื่อ app อื่นเปิดของคุณโดยการเปิด URL ด้วยรูปแบบที่แอปของคุณรองรับ ไม่เรียกว่าเมื่อแอปของคุณเริ่มเปิด URL
ฉันคิดว่าวิธีเดียวที่จะทำในสิ่งที่ Vladimir ต้องการคือใช้ UIWebView แทน UITextView ทำให้ตัวควบคุมมุมมองของคุณใช้ UIWebViewDelegate ตั้งค่าผู้รับมอบสิทธิ์ของ UIWebView เป็นตัวควบคุมมุมมองและในตัวควบคุมมุมมองใช้webView:shouldStartLoadWithRequest:navigationType:
เพื่อเปิด[request URL]
ในมุมมองแทนที่จะออกจากแอปของคุณและเปิดใน Mobile Safari