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 UIText
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
}
}
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 UITextView
s 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.
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;
}