How To Implement a Twitter Feed in SwiftUI in Less Than 200 Lines Of Code

Learn how to implement a Twitter feed in SwiftUI without any API access credentials using SwiftUI and WebKit.

Published by Philipp Matthes 2 months, 3 weeks ago

Taking the fact that Twitter recently deprecated their native TwitterKit library, we needed to search for a new alternative for our OUTPUT.DD iOS App and came up with something that is really simple and straightforward. The basic idea is to use a WKWebView, which loads the Twitter widget and displays the desired Twitter feed.

This tutorial was written for Swift Version: 5.3

The HTML Template

Create a new file and name it TwitterViewTemplate.html. Make sure it is included in the app’s bundle, since we are going to load it from there later.

<!-- This is an html template for displaying a Twitter feed using the twitter widget. -->
<meta name='viewport' content='initial-scale=1'/>
<a class="twitter-timeline" href=""></a>
<script async src="" charset="utf-8"></script>

The template will be rendered in its own WKWebView, to which we will get in a moment. The basic idea is that the Template loads the Twitter widgets JavaScript from the official Twitter server. Afterwards, the Twitter widget replaces our <a> with an actual HTML feed, which has basically the same UI as you already know it from Twitter. Note that the Template updates itself automatically, which is very convenient!

The SwiftUI HTML View

Since SwiftUI doesn’t natively support the WKWebView yet, we will create our own custom wrapper. Create a new file called TwitterHTMLView.swift and insert the following code:

import SwiftUI
import WebKit

/// A state indicating the loading state of the WebView.
enum TwitterHTMLViewState {
    case loading
    case idle

/// A simple navigation delegate for the twitter html view.
/// The delegate enables the webview to open tweets in the default browser.
fileprivate class TwitterHTMLViewNavigator: NSObject, WKNavigationDelegate {
    private let onStateChange: (TwitterHTMLViewState) -> Void

    init(onStateChange: @escaping (TwitterHTMLViewState) -> Void) {
        self.onStateChange = onStateChange

    func webView(
        _ webView: WKWebView,
        decidePolicyFor navigationAction: WKNavigationAction,
        decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
    ) {
        guard navigationAction.navigationType == .linkActivated else {
            let url = navigationAction.request.url,
        else {

    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        // This method is called when the WebView is loading.

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // This method is called when the WebView finished loading.

/// A html view based on WKWebView which wraps a simple twitter feed.
struct TwitterHTMLView: UIViewRepresentable {
    private let navigator: WKNavigationDelegate

    init(onStateChange: @escaping (TwitterHTMLViewState) -> Void) {
        self.navigator = TwitterHTMLViewNavigator(
            onStateChange: onStateChange

    func makeUIView(context: Context) -> WKWebView {
        let view = WKWebView(frame: .zero)
            let htmlFilepath = Bundle.main.path(
                forResource: "TwitterViewTemplate", ofType: "html"
            let html = try? String(contentsOfFile: htmlFilepath)
        else { fatalError("Twitter Assets not found!") }
        view.loadHTMLString(html, baseURL: nil)
        view.navigationDelegate = navigator
        return view

    func updateUIView(
        _ view: WKWebView,
        context: UIViewRepresentableContext<TwitterHTMLView>
    ) { /* Protocol requirement */}

This SwiftUI HTML view now automatically loads our HTML template and the included Twitter widget, which loads the Twitter feed. We use a navigation delegate to get notified of three events:

The TwitterView including Loading Indicators

Now, to conclude, we create a TwitterView.swift file to wrap our TwitterHTMLView and react to any loading state changes. Also, we add a custom toolbar action for our navigation view to create a new Tweet.

import SwiftUI

/// A twitter view which shows the output.dd twitter feed.
struct TwitterView: View {
    @State private var isLoading = true

    private var newTweetURL: URL {
        // Create a new tweet with @OUTPUT.DD as text (urlencoded)
        let urlString = ""
            let url = URL(string: urlString)
        else { fatalError("Erroneous tweet url detected!") }
        return url

    var body: some View {
        NavigationView {
            ZStack {
                TwitterHTMLView { loadingState in
                    switch loadingState {
                    case .idle:
                        isLoading = false
                    case .loading:
                        isLoading = true
                if isLoading {
                    VStack {
                        Text("Loading Twitter Feed...")
            .toolbar {
                ToolbarItem(placement: .automatic) {
                    Link(destination: newTweetURL, label: {
                        HStack {
                            Image(systemName: "plus")

This is how the finished TwitterView looks like in Xcode:



You can download the views for free here:

Thank you for reading, if this did help you, give me a shoutout or buy me a coffee, if you want to 😎

swift swiftui twitter feed webkit tutorial

More Blog Entries for You

Postprocessing FCRN Depth Maps on iOS Devices with Custom Filtering

Published by Philipp Matthes 2 months ago

The FCRN neural network can be used to interpret depth maps on single-lens camera images. But how can we further improve the depth maps based on the intial photo?

Read Blog Entry

Vortrag: Microservices, DevOps und Containerisierung im Cloud Computing

Published by Felix Kästner and Philipp Matthes 2 months, 3 weeks ago

Wir haben einen Vortrag für OUTPUT.DD eingereicht zum Thema "Microservices und Containerisierung im Cloud Computing"!

Read Blog Entry