Implementing Search Functionality in UIWebView for iOS Apps

Understanding UIWebView Search Functionality

As a developer, have you ever found yourself in a situation where you need to integrate search functionality into an app that displays content loaded from an external source, such as a web view? This is a common scenario when building apps that display web pages or load HTML content. In this article, we’ll delve into the details of implementing search functionality within a UIWebView control on iOS devices.

What is UIWebView?

Before we dive into the search functionality, it’s essential to understand what UIWebView is and how it works. UIWebView is a view that displays an HTML or HTML5 content. It allows you to load web pages, embed HTML documents, or display custom content within your app. This control provides an easy way to integrate web-based content into your iOS app.

Implementing Search Functionality in UIWebView

The search functionality we’re going to implement is similar to the one found in Safari’s address bar. When you press Cmd + F, the app will highlight the text that contains the search query. This can be achieved using a combination of JavaScript, HTML, and iOS APIs.

To start with, let’s create a basic UIWebView controller that loads an HTML file from our project directory:

// ViewController.m

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic, strong) UIWebView *webView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Load the HTML file into the web view
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
    NSURL *fileURL = [NSURL fileURLWithPath:filePath];
    [self.webView loadRequest:[NSURLRequest requestWithURL:fileURL]];

    // Configure the search functionality
    self.webView.delegate = self;
}

In this code snippet, we’re loading an HTML file named index.html from our project directory into the UIWebView.

Configuring Search Functionality

To implement the search functionality, we’ll override two methods in the UIWebViewDelegate protocol: webView:didFindTextInRange:matchType:direction:rangeOrigin: and webView(_:shouldBeginPageLoadWith:options:error:). These methods are called when the web view finds a match for the search query.

Here’s how you can implement these methods:

// ViewController.m

@implementation ViewController

- (void)webView:(UIWebView *)webView didFindTextInRange:(NSRange)range
    matchType:(WKWebQueryMatchType)matchType
        direction:(WKEffectiveDirection)direction
           rangeOrigin:(NSRange)rangeOrigin
            error:(NSError **)error {
    // If a match is found, highlight the text
    if (matchType == WKWebQueryMatchTypeSearchText) {
        [self highlightMatchingText:range];
    }
}

- (void)webView:(UIWebView *)webView shouldBeginPageLoadWithOptions:(NSDictionary<WKNavigationOptionsKey, id> *)options error:(NSError **)error {
    // Do not allow the default keyboard to appear when searching
    WKWebpagePrefetchResult result = [self.webView prefetchPageWithWebpageOptions:options options:0];
    if (result == WKWebpagePrefetchResultContinue) {
        return YES;
    }
    return NO;
}

- (void)highlightMatchingText:(NSRange)range {
    // Get the HTML content of the web view
    NSString *html = [self.webView stringByEvaluatingHTMLString:self.webView.string error:nil];

    // Extract the text that matches the search query
    NSString *searchQuery = [self.webView stringByEvaluatingHTMLString:@"<input type='text' id='search' value='' />" error:nil];
    NSRange searchRange = NSMakeRange(0, html.length);
    NSRange matchingRange = NSMakeRange(searchRange.location, 0);
    while (matchingRange.location < searchRange.location) {
        int count = [html rangeOfString:searchQuery options:NSMatchingWholeWord range:&matchingRange rangeLimit:NSNoIndex];
        if (count > 0) {
            matchingRange = NSMakeRange(matchingRange.location + count, matchingRange.length);
        } else {
            break;
        }
    }

    // Highlight the matching text
    [self.webView evaluateJavaScript:@"document.getElementById('search').value = ''" completionHandler:nil];

    // Get the highlighted text
    NSString *highlightedText = [html substringWithRange:matchingRange];

    // Set the background color to indicate highlighting
    [self.webView evaluateJavaScript:@"var range = document.createRanges(); range[0].startContainer = this; range[0].endContainer = this; var selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range[0]);" completionHandler:nil];
}

In this code snippet, we’re extracting the search query from the HTML content of the web view using byStringEvaluatingHTMLString:error:. We’re then finding the matching text in the HTML content by checking if there are any occurrences of the search query within the text.

To highlight the matching text, we’re creating a range object using document.createRanges() and setting its start and end containers to the same container as the matched text. This is done using JavaScript. We then add this range object to the selection range in the web view’s document object model (DOM).

UIWebViewDelegate Methods

Here are some other delegate methods you might need to implement depending on your needs:

shouldBeginLoadURL

This method is called when a new URL is requested by the web view.

- (BOOL)webView:(UIWebView *)webView shouldBeginLoadURL:(NSURL *)url options:NSDictionary<WKNavigationOptionsKey, id> *options error:NSError **error {
    // Do not allow loading of URLs with certain schemes
    if ([url scheme] == @"https") {
        return NO;
    }
    return YES;
}

didFailLoadWithError

This method is called when the web view fails to load a URL.

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    // Handle errors gracefully
    NSLog(@"Error loading page: %@", error.localizedDescription);
}

loadFinished

This method is called when the web view finishes loading a URL.

- (void)webViewDidFinishLoading:(UIWebView *)webView {
    // Release resources
    self.webView = nil;
}

Conclusion

In this article, we explored how to implement search functionality in UIWebView on iOS devices. We discussed the requirements for implementing search functionality and created a basic example that loads an HTML file from our project directory into the web view. We also implemented the delegate methods necessary to highlight matching text within the web view.

With this knowledge, you should be able to create your own UIWebView app with search functionality similar to Safari’s address bar.


Last modified on 2024-04-14