Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to open UITextView web links in a UIWebView instead of Safari?

I'm developing and iPhone 3.0 application. And I'm trying to open web links in a UITextView into a UIWebView instead of Safari. But still no luck.

The UITextView is not editable, and it perfectly detects web links and open them in Safari.

How to avoid that? How to grab that url so i can use with my own UIWebView?

like image 294
lucadb Avatar asked Aug 20 '09 11:08

lucadb


3 Answers

This is an old question but incase anyone is looking for an updated way of doing this.

Assign your viewController that holds the UITextView as a delegate in your viewController's .m file and just add:

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

    //Do something with the URL
    NSLog(@"%@", URL);


    return NO;
}
like image 106
nihad Avatar answered Nov 19 '22 17:11

nihad


With Swift 3, UITextViewDelegate provides a textView(_:shouldInteractWith:in:interaction:) method. textView(_:shouldInteractWith:in:interaction:) has the following declaration:

Asks the delegate if the specified text view should allow the specified type of user interaction with the given URL in the given range of text.

optional func textView(_ textView: UITextView,  shouldInteractWith URL: URL,  in characterRange: NSRange,  interaction: UITextItemInteraction) -> Bool

The following code shows how to open UITextView web links in a SFSafariViewController instead of opening them in Safari app:

import UIKit
import SafariServices

class ViewController: UIViewController, UITextViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set textView
        let textView = UITextView()
        textView.text = "http://www.yahoo.fr http://www.google.fr"
        textView.isUserInteractionEnabled = true
        textView.isEditable = false
        textView.isSelectable = true
        textView.dataDetectorTypes = UIDataDetectorTypes.link

        // Add view controller as the textView's delegate
        textView.delegate = self

        // auto layout
        view.addSubview(textView)
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        textView.heightAnchor.constraint(equalToConstant: 300).isActive = true
        textView.widthAnchor.constraint(equalToConstant: 300).isActive = true
    }

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        // Open links with a SFSafariViewController instance and return false to prevent the system to open Safari app
        let safariViewController = SFSafariViewController(url: URL)
        present(safariViewController, animated: true, completion: nil)

        return false
    }

}
like image 8
Imanou Petit Avatar answered Nov 19 '22 17:11

Imanou Petit


The simplest way is to override the webView:decidePolicyForNavigationAction:request:frame:decisionListener: method on UITextView like so:

@interface UITextView (Override)
@end

@class WebView, WebFrame;
@protocol WebPolicyDecisionListener;

@implementation UITextView (Override)

- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id < WebPolicyDecisionListener >)listener
{
    NSLog(@"request: %@", request);
}
@end

This will affect all UITextViews in your application. If you only require this on a single view, create a subclass and override the method on that.

Note: this is technically a private API and could be removed at any time. There is no way to do this via the public API.

edit: as of iOS 7.0 a new method has been introduced on UITextViewDelegate to support this. See nihad's answer for details.

like image 7
rpetrich Avatar answered Nov 19 '22 19:11

rpetrich