Implementing a Custom URL Opener in a Modal View Controller
In this article, we will explore how to create a custom URL opener that opens links in a modal view controller instead of the default safari browser. We will delve into the challenges of extracting URLs from a UITextView and intercepting the call to open a link, as well as provide a solution using a combination of UIKit and WKWebView.
Understanding the Challenges
The first challenge we face is extracting the URL from the UITextView. This is because the text in the UITextView may contain multiple URLs, and we need to identify the specific one that needs to be opened. The second challenge is intercepting the call to open a link, which is typically handled by the safari browser.
Extracting the URL from a UITextView
To extract the URL from a UITextView, we can use a combination of regular expressions and string manipulation techniques. Here’s an example code snippet that demonstrates how to do this:
#import <Foundation/Foundation.h>
@interface UITextView (URLExtractor)
- (NSArray<NSString *> *)urls;
@end
@implementation UITextView (URLExtractor)
- (NSArray<NSString *> *)urls {
NSString *text = self.text;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(https?://\\S+)" options:NSRegularExpressionCaseInsensitive error:nil];
NSArray<NSURL *> *matches = [regex matchesInString:text range:NSMakeRange:0, text.length];
return matches.map:^(NSError * _Nullable error) {
NSURL *url = [matches.firstObject absoluteURL];
return url.absoluteString;
};
}
@end
Intercepting the Call to Open a Link
To intercept the call to open a link, we can use a combination of UIWebViewDelegate and WKWebViewDelegate. Here’s an example code snippet that demonstrates how to do this:
#import <WebKit/WebKit.h>
@interface ViewController () <WKWebViewDelegate>
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:nil];
self.webView.delegate = self;
[self.view addSubview:self.webView];
}
#pragma mark - WKWebViewDelegate
- (void)webView:(WKWebView *)webView didReceiveResponse:(WKNetworkResourceResponse *)response completionHandler:(void (^)(WKNetworkResourceResponse *))completionHandler {
if ([response.request URL].absoluteString contains@"://") {
NSString *url = response.request.URL.absoluteString;
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
completionHandler(NO);
}
}
- (void)webView:(WKWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(@"Failed to load URL: %@", error);
}
- (void)webView:(WKWebView *)webView didStartLoad:(WKNavigation *)navigation {
NSLog(@"Started loading URL: %@", navigation.request.URL.absoluteString);
}
@end
Creating a Custom URL Opener
Now that we have the code snippets above, let’s create a custom URL opener that opens links in a modal view controller. Here’s an example code snippet that demonstrates how to do this:
#import <UIKit/UIKit.h>
@interface ModalViewController : UIViewController
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ModalViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:nil];
self.webView.delegate = self;
[self.view addSubview:self.webView];
}
#pragma mark - WKWebViewDelegate
- (void)webView:(WKWebView *)webView didReceiveResponse:(WKNetworkResourceResponse *)response completionHandler:(void (^)(WKNetworkResourceResponse *))completionHandler {
if ([response.request URL].absoluteString contains@"://") {
NSString *url = response.request.URL.absoluteString;
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
completionHandler(NO);
}
}
- (void)webView:(WKWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(@"Failed to load URL: %@", error);
}
- (void)webView:(WKWebView *)webView didStartLoad:(WKNavigation *)navigation {
NSLog(@"Started loading URL: %@", navigation.request.URL.absoluteString);
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.example.com"]]];
}
@end
Using the Custom URL Opener
To use the custom URL opener, we need to create an instance of ModalViewController and push it onto the navigation stack. Here’s an example code snippet that demonstrates how to do this:
#import <UIKit/UIKit.h>
@interface ViewController () <WKWebViewDelegate>
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:nil];
self.webView.delegate = self;
[self.view addSubview:self.webView];
}
#pragma mark - WKWebViewDelegate
- (void)webView:(WKWebView *)webView didReceiveResponse:(WKNetworkResourceResponse *)response completionHandler:(void (^)(WKNetworkResourceResponse *))completionHandler {
if ([response.request URL].absoluteString contains@"://") {
NSString *url = response.request.URL.absoluteString;
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
completionHandler(NO);
}
}
- (void)webView:(WKWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(@"Failed to load URL: %@", error);
}
- (void)webView:(WKWebView *)webView didStartLoad:(WKNavigation *)navigation {
NSLog(@"Started loading URL: %@", navigation.request.URL.absoluteString);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue {
if ([segue.identifier isEqualToString:@"ShowModalViewController"]) {
ModalViewController *modalViewController = segue.destinationViewController;
self.webView.loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.example.com"]];
}
}
@end
In this example, we create an instance of WKWebView and assign it to the webView property. We also implement the WKWebViewDelegate methods to handle the loading of URLs.
We then create a segue from our main view controller to the modal view controller using Storyboard or programmatically.
Finally, when the modal view controller is presented, we load the URL into the WKWebView.
This is how you can create a custom URL opener that opens links in a modal view controller.
Last modified on 2024-12-05