2010-03-30 29 views
84

Có thể thực hiện tác vụ tùy chỉnh khi người dùng chạm vào liên kết điện thoại được tự động phát hiện trong UITextView hay không. Vui lòng không khuyên dùng UIWebView thay thế.Làm cách nào để chặn nhấp chuột vào liên kết trong UITextView?

Và vui lòng không chỉ lặp lại văn bản từ các lớp học táo tham khảo - chắc chắn tôi đã đọc nó.

Cảm ơn.

Trả lời

120

Cập nhật: Từ iOS 7 và sau UITextView có phương pháp đại biểu:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange 

để đánh chặn các nhấp chuột vào các liên kết. Và đây là cách tốt nhất để làm điều đó.

Đối với iOS 6 và trước đó một cách tốt đẹp để làm điều này là bởi subclassing UIApplication và ghi đè lên các -(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 thực hiện openURL: trong đoàn của bạn.

Bây giờ, để ứng dụng bắt đầu với lớp con mới của bạn là UIApplication, hãy tìm tệp main.m trong dự án của bạn. Trong tệp nhỏ này khởi động ứng dụng của bạn, thường có dòng này:

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 cho tôi.

+0

Ở câu trả lời thực sự cuối cùng! Ý tưởng đơn giản và thú vị. Cảm ơn, nó hoạt động. Đã lâu lắm rồi, nên tôi đã xoay xở mà không có nó. Vẫn có thể giúp đỡ trong tương lai. Chỉnh sửa nhỏ mặc dù, kết quả từ siêu trong chi nhánh khác nên được trả lại: return [super openURL: url]; – Vladimir

+0

Tuyệt! Tôi đã thực hiện điều chỉnh được đề xuất. Chúc mừng! – fsaint

+2

Bạn cũng có thể phân loại 'UIApplication' và thay thế việc triển khai openURL. Mặc dù theo cách này nó là khó khăn (nhưng không phải không thể) để tham khảo thực hiện ban đầu. – mxcl

0

Tôi chưa thử bản thân mình nhưng bạn có thể thử triển khai phương thức application:handleOpenURL: trong ủy nhiệm ứng dụng của mình - có vẻ như tất cả yêu cầu openURL đều được chuyển qua cuộc gọi lại này.

0

Không chắc chắn cách bạn sẽ chặn liên kết dữ liệu được phát hiện 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 didBeginEditing TextField để chạy thử nghiệm/quét qua trường văn bản nếu bạn biết tìm kiếm của mình ... như so sánh các chuỗi văn bản đáp ứng ### - ### - #### format, hoặc bắt đầu bằng "www." để lấy những trường đó, nhưng bạn sẽ cần phải viết một đoạn mã nhỏ để xem qua chuỗi textfields, reconise những gì bạn cần, và sau đó giải nén nó để sử dụng chức năng của bạn. Tôi không nghĩ rằng điều này sẽ là khó khăn, một khi bạn thu hẹp chính xác những gì nó là bạn muốn và sau đó tập trung của bạn if() tuyên bố lọc xuống mô hình phù hợp rất cụ thể của những gì bạn cần.

Điều này có nghĩa là người dùng sẽ chạm vào hộp văn bản để kích hoạt didBeginEditing(). Nếu đó không phải là loại tương tác người dùng bạn đang tìm kiếm, bạn có thể sử dụng Bộ hẹn giờ kích hoạt, bắt đầu trên ViewDidAppear() hoặc dựa trên nhu cầu khác và chạy qua chuỗi văn bản, sau đó kết thúc bạn chạy qua chuỗi textfield phương pháp mà bạn đã xây dựng, bạn chỉ cần bật lại Bộ hẹn giờ.

0

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ở 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ĩ cách duy nhất để làm những gì Vladimir muốn là sử dụng UIWebView thay vì UITextView. Làm cho trình điều khiển xem của bạn triển khai UIWebViewDelegate, đặt giao diện người dùng của UIWebView cho trình điều khiển chế độ xem và trong trình điều khiển chế độ xem thực hiện webView:shouldStartLoadWithRequest:navigationType: để mở [request URL] trong chế độ xem thay vì thoát ứng dụng của bạn và mở ứng dụng đó trong Mobile Safari.

44

Trong iOS 7 trở lên

Bạn có thể sử dụng phương pháp UITextView đại biểu sau đây:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange 

Quan điểm văn bản gọi phương pháp này nếu các vòi sử dụng hoặc dài nhấn vào liên kết URL. 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 mở ứng dụng chịu trách nhiệm xử lý loại URL và chuyển URL đó. 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.

Chú ý:

Liên kết trong quan điểm văn bản là tương tác chỉ khi độ xem văn bản là lựa chọn nhưng noneditable. Nghĩa là, nếu giá trị của UITextView thuộc tính có thể chọn là CÓ và thuộc tính có thể chỉnh sửa là KHÔNG.

+0

Tôi rất vui vì họ đã thêm điều này vào UITextViewDelegate. – fsaint

+0

Rất tiếc, bạn vẫn sẽ sử dụng 'UIWebView' nếu bạn muốn tạo một số văn bản khác * liên kết * chứ không phải chính URL đó. Thẻ '' vẫn là cách tốt nhất để đi trong trường hợp đó. –

3

phiên bản Swift:

thiết lập UITextView tiêu chuẩn của bạn sẽ giống như thế này, đừng quên các đại biểu 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 thêm mảnh 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 
    } 
} 
1

Tôi có nội dung động theo quan điểm văn bản, mà có thể chứa liên kết. Các shouldInteractWithURL là nhận được gọi là chỉ khi người dùng là dài báo chí trên liên kết nhưng không gọi trên vòi liên kết. Vui lòng chuyển hướng nếu có bất kỳ người bạn nào tham chiếu đến nó.

Sau đây là một số mã được quét.

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; 
} 

Phương thức đại biểu trên không được gọi trên vòi.

Kính trọng, Rohit Jankar

2

Với Swift 3 và i0S 10, cách đơn giản nhất để tương tác với các số điện thoại, url hoặc địa chỉ trong UITextView là sử dụng UIDataDetectorTypes. Mã bên dưới cho biết cách hiển thị số điện thoại trong một số UITextView để người dùng có thể tương tác với nó.

import UIKit 

class ViewController: UIViewController { 

    // Link this outlet to a UITextView in your Storyboard 
    @IBOutlet weak var textView: UITextView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     textView.text = "+33687654321" 
     textView.isUserInteractionEnabled = true // default: true 
     textView.isEditable = false // default: true 
     textView.isSelectable = true // default: true 
     textView.dataDetectorTypes = [.phoneNumber] 
    } 

} 

Với mã này, khi nhấp vào số điện thoại, UIAlertController sẽ bật lên.


Là một thay thế, bạn có thể sử dụng NSAttributedString:

import UIKit 

class ViewController: UIViewController { 

    // Link this outlet to a UITextView in your Storyboard 
    @IBOutlet weak var textView: UITextView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works 
     let attributes = [NSLinkAttributeName: phoneUrl] 
     let attributedString = NSAttributedString(string: "phone number", attributes: attributes) 

     textView.attributedText = attributedString 
     textView.isUserInteractionEnabled = true // default: true 
     textView.isEditable = false // default: true 
     textView.isSelectable = true // default: true 
    } 

} 

Với mã này, khi nhấp vào chuỗi do, một UIAlertController sẽ bật lên.


Tuy nhiên, bạn có thể thực hiện một số hành động tùy chỉnh thay vì thực hiện UIAlertController bật lên khi bạn nhấp vào số điện thoại. Hoặc bạn có thể muốn giữ một số UIAlertController để bật lên và thực hiện hành động tùy chỉnh của riêng bạn trong cùng một thời điểm.

Trong cả hai trường hợp, bạn sẽ phải thực hiện UIViewController của mình tuân theo giao thức UITextViewDelegate và triển khai textView(_:shouldInteractWith:in:interaction:). Mã dưới đây cho thấy cách thực hiện.

import UIKit 

class ViewController: UIViewController, UITextViewDelegate { 

    // Link this outlet to a UITextView in your Storyboard 
    @IBOutlet weak var textView: UITextView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     textView.delegate = self 

     textView.text = "+33687654321" 
     textView.isUserInteractionEnabled = true 
     textView.isEditable = false 
     textView.isSelectable = true 
     textView.dataDetectorTypes = [.phoneNumber] 
    } 

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { 
     /* perform your own custom actions here */ 
     print(URL) 

     return false // return true if you still want UIAlertController to pop up 
    } 

} 

Với mã này, khi nhấp vào số điện thoại, không có UIAlertController sẽ bật lên và thay vào đó bạn sẽ nhận được in sau trong giao diện điều khiển của bạn:

tel: +33687654321

3

Đố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 
0

Swift 4:

1) Tạo lớp sau (subclassed 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) Bất cứ nơi nào bạn thiết lập TextView của mình, làm điều này:

//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 kịch bản, đảm bảo TextView của bạn trông như thế này trong thanh tra danh tính khung bên phải:
enter image description here



Voila! Bây giờ bạn nhận được liên kết nhấn ngay lập tức thay vì khi URL nênInteractWith phương pháp URL

+0

cũng: nếu bạn muốn url không được xử lý, chỉ cần thiết lập phương thức shouldInteractWith để trả về false –

+0

Hãy nghĩ rằng điều này có một loạt vấn đề, chẳng hạn như những gì xảy ra khi bạn không nhấn vào một liên kết. Tức là tôi không nghĩ rằng các văn bản xem sẽ làm việc bình thường nữa, kể từ khi nil đang được trả lại. Lựa chọn cũng sẽ thay đổi khi bạn nhấn vào một liên kết, bởi vì trong trường hợp đó, tự quay trở lại. –

+0

hoạt động tốt cho tôi, bạn cần xử lý các trường hợp như vậy cho nhu cầu của mình –

Các vấn đề liên quan