UIWebView
iOS development
load local HTML
Swift programming
Xcode tips

How to load local html file into UIWebView

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Loading a bundled HTML file into UIWebView was a common pattern in older iOS apps for help screens, local documentation, and hybrid content. The mechanics are straightforward: include the HTML file in the app bundle, build a file URL, and load it with a base URL that lets related assets resolve correctly. The important caveat is that UIWebView is legacy API, so new code should use WKWebView, but the loading model is still useful to understand for maintenance work.

Put the HTML File in the App Bundle

The first requirement is that the HTML file, plus any CSS, images, and JavaScript it references, are copied into the target bundle.

For example, suppose the bundle contains:

  • 'index.html'
  • 'styles.css'
  • 'logo.png'

If those files are not part of the app target, no amount of code will load them correctly. In Xcode, the file must be included in the target's build resources.

Load by File URL

The most direct pattern is to locate the HTML file in the bundle and load it from a file URL.

swift
1import UIKit
2
3final class HelpViewController: UIViewController {
4    private let webView = UIWebView(frame: .zero)
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        view.addSubview(webView)
9        webView.frame = view.bounds
10        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
11
12        guard let url = Bundle.main.url(forResource: "index", withExtension: "html") else {
13            assertionFailure("Missing bundled HTML file")
14            return
15        }
16
17        let request = URLRequest(url: url)
18        webView.loadRequest(request)
19    }
20}

That works when the HTML file is self-contained or uses relative paths that can resolve from the file location.

Use loadHTMLString With a Base URL When Needed

If you want to read the HTML contents yourself, or modify the HTML before loading it, you can use loadHTMLString. The important part is providing a base URL so relative resources still work.

swift
1import UIKit
2
3final class LocalHTMLViewController: UIViewController {
4    private let webView = UIWebView(frame: .zero)
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        view.addSubview(webView)
9        webView.frame = view.bounds
10        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
11
12        guard let htmlURL = Bundle.main.url(forResource: "index", withExtension: "html"),
13              let html = try? String(contentsOf: htmlURL, encoding: .utf8) else {
14            assertionFailure("Unable to read bundled HTML")
15            return
16        }
17
18        let baseURL = htmlURL.deletingLastPathComponent()
19        webView.loadHTMLString(html, baseURL: baseURL)
20    }
21}

This version is especially useful if the HTML references styles.css or images with relative paths. Without the correct base URL, those related files may fail to load.

Why the Base URL Matters

Suppose index.html contains:

html
<link rel="stylesheet" href="styles.css">
<img src="logo.png" alt="Logo">

Those asset paths are relative. If the web view does not know the file-system directory that should act as the base, it has no way to locate them correctly. That is why loadHTMLString without a meaningful base URL often shows raw HTML layout with missing styles and images.

Prefer WKWebView for New Code

Even though this article is about UIWebView, the maintenance reality is that WKWebView is the modern replacement. If you are touching this code in an app that is still evolving, consider whether the better fix is migration rather than refining legacy loading calls.

The equivalent WKWebView API for local file loading looks like this:

swift
1import WebKit
2
3let webView = WKWebView(frame: .zero)
4let url = Bundle.main.url(forResource: "index", withExtension: "html")!
5webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())

That is usually the better long-term direction, but legacy UIWebView codebases still benefit from understanding the older pattern.

Common Pitfalls

  • Adding the HTML file to the project but not to the app target's build resources.
  • Loading an HTML string without a correct base URL, which breaks relative CSS, image, or script paths.
  • Assuming missing local assets are a web-view bug when the bundle path is actually wrong.
  • Treating UIWebView as a modern default instead of recognizing it as legacy code that should usually migrate to WKWebView.
  • Hardcoding file-system paths instead of using Bundle.main to resolve resources safely.

Summary

  • To load local HTML in UIWebView, put the files in the bundle and load them by bundle URL.
  • 'loadRequest is fine for simple file loading, while loadHTMLString is useful when you also need to supply a base URL.'
  • Relative assets such as CSS and images depend on the base URL being correct.
  • Bundle membership problems are a common reason local HTML appears not to load.
  • For new work, prefer WKWebView, but the legacy UIWebView pattern is still useful for maintaining older apps.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.