Add URLScheme
Core
@main
struct SwiftUIDeepLinkApp: App {
    @StateObject var appData: AppDataModel = AppDataModel()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appData)
                .onOpenURL { url in
                    // used to fetch the deep link url...
                    print("incoming url: \(url)")
                    if appData.checkDeepLink(url: url) {
                        print("FROM DEEP LINK")
                    } else {
                        print("FALL BACK DEEP LINK")
                    }
                }
        }
    }
}
 
//
//  AppDataModel.swift
//  SwiftUIDeepLink
//
//  Created by paige on 2022/01/14.
//
import Combine
import Foundation
class AppDataModel: ObservableObject {
    @Published var currentTab: Tab = .home
    @Published var currentDetailPage: String?
    func checkDeepLink(url: URL) -> Bool {
        guard let host = URLComponents(url: url, resolvingAgainstBaseURL: true)?.host else {
            return false
        }
        // Updating Tabs...
        if host == Tab.home.rawValue {
            // paigesoftware://home
            currentTab = .home
        } else if host == Tab.search.rawValue {
            // paigesoftware://search
            currentTab = .search
        } else if host == Tab.settings.rawValue {
            // paigesoftware://settings
            currentTab = .settings
        } else {
            return checkInternalLinks(host: host)
        }
        return true
    }
    func checkInternalLinks(host: String) -> Bool {
        // paigesoftware://CCFFB11
        // checking if host contains any navigation link ids...
        if let index = coffees.firstIndex(where: { coffee in
            return coffee.id == host
        }) {
            // Chaning to search tab...
            // since navigation links are in search tab
            currentTab = .search
            // setting nav link selection...
            self.currentDetailPage = coffees[index].id
            return true
        }
        return false
    }
}
// Tab enum...
enum Tab: String {
    case home = "home"
    case search = "search"
    case settings = "settings"
}
 
struct Home: View {
    @EnvironmentObject var appData: AppDataModel
    var body: some View {
        TabView(selection: $appData.currentTab) {
            Text("Home")
                .tag(Tab.home)
                .tabItem {
                    Image(systemName: "house.fill")
                }
            SearchView()
                .environmentObject(appData)
                .tag(Tab.search)
                .tabItem {
                    Image(systemName: "magnifyingglass")
                }
            Text("Settings")
                .tag(Tab.settings)
                .tabItem {
                    Image(systemName: "gear")
                }
        }
    }
}
 
 NavigationLink(tag: coffee.id, selection: $appData.currentDetailPage) {
                  detailView(coffee: coffee)
              } label: {
}
 
NavigationView {
            List {
                // List of availble coffees.
                ForEach(coffees) { coffee in
                    // Setting tag and selection so that whenever we update selection
                    // that navigation link will be called...
                    NavigationLink(tag: coffee.id, selection: $appData.currentDetailPage) {
                        detailView(coffee: coffee)
                    } label: {
                        HStack(spacing: 15) {
                            Image(coffee.productImage)
                                .resizable()
                                .aspectRatio(contentMode: .fill)
                                .frame(width: 80, height: 80)
                                .cornerRadius(15)
                            VStack(alignment: .leading, spacing: 10) {
                                Text(coffee.title)
                                    .font(.title2.bold())
                                    .foregroundColor(.primary)
                                Text(coffee.productPrice)
                                    .font(.callout)
                                    .fontWeight(.semibold)
                                    .foregroundColor(.gray)
                            }
                        }
                    }
                }
            }
            .navigationTitle("Search")
            // to show demo how it works...
//            .toolbar {
//                Button("GOTO NAV LINK 3") {
//                    appData.currentDetailPage = coffees[2].id
//                }
//            }
        }
 
Model
struct Coffee: Identifiable {
    var id: String
    var title: String
    var description: String
    var productImage: String
    var productPrice: String
}
var coffees: [Coffee] = [
    Coffee(id: "CCFFB11", title: "1", description: "", productImage: "1", productPrice: "$17"),
    Coffee(id: "CCFFB12", title: "2", description: "", productImage: "2", productPrice: "$17"),
    Coffee(id: "CCFFB13", title: "3", description: "", productImage: "3", productPrice: "$17"),
    Coffee(id: "CCFFB14", title: "4", description: "", productImage: "4", productPrice: "$17"),
    Coffee(id: "CCFFB15", title: "5", description: "", productImage: "5", productPrice: "$17"),
    Coffee(id: "CCFFB16", title: "6", description: "", productImage: "6", productPrice: "$17"),
]
 
App Data Model
//
//  AppDataModel.swift
//  SwiftUIDeepLink
//
//  Created by paige on 2022/01/14.
//
import Combine
import Foundation
class AppDataModel: ObservableObject {
    @Published var currentTab: Tab = .home
    @Published var currentDetailPage: String?
    func checkDeepLink(url: URL) -> Bool {
        guard let host = URLComponents(url: url, resolvingAgainstBaseURL: true)?.host else {
            return false
        }
        // Updating Tabs...
        if host == Tab.home.rawValue {
            // paigesoftware://home
            currentTab = .home
        } else if host == Tab.search.rawValue {
            // paigesoftware://search
            currentTab = .search
        } else if host == Tab.settings.rawValue {
            // paigesoftware://settings
            currentTab = .settings
        } else {
            return checkInternalLinks(host: host)
        }
        return true
    }
    func checkInternalLinks(host: String) -> Bool {
        // paigesoftware://CCFFB11
        // checking if host contains any navigation link ids...
        if let index = coffees.firstIndex(where: { coffee in
            return coffee.id == host
        }) {
            // Chaning to search tab...
            // since navigation links are in search tab
            currentTab = .search
            // setting nav link selection...
            self.currentDetailPage = coffees[index].id
            return true
        }
        return false
    }
}
// Tab enum...
enum Tab: String {
    case home = "home"
    case search = "search"
    case settings = "settings"
}
 
App
//
//  SwiftUIDeepLinkApp.swift
//  SwiftUIDeepLink
//
//  Created by paige on 2022/01/14.
//
import SwiftUI
@main
struct SwiftUIDeepLinkApp: App {
    @StateObject var appData: AppDataModel = AppDataModel()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appData)
                .onOpenURL { url in
                    // used to fetch the deep link url...
                    print("incoming url: \(url)")
                    if appData.checkDeepLink(url: url) {
                        print("FROM DEEP LINK")
                    } else {
                        print("FALL BACK DEEP LINK")
                    }
                }
        }
    }
}
// Integrating Deep Link...
// First create a url scheme for how to call your url...
// EG: paigesoftware
// calling will be done like `paigesoftware://`
 
ContentView
//
//  ContentView.swift
//  SwiftUIDeepLink
//
//  Created by paige on 2022/01/14.
//
import SwiftUI
struct ContentView: View {
    @EnvironmentObject var appData: AppDataModel
    var body: some View {
        Home()
            .environmentObject(appData)
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
 
Home
//
//  Home.swift
//  SwiftUIDeepLink
//
//  Created by paige on 2022/01/14.
//
import SwiftUI
struct Home: View {
    @EnvironmentObject var appData: AppDataModel
    var body: some View {
        TabView(selection: $appData.currentTab) {
            Text("Home")
                .tag(Tab.home)
                .tabItem {
                    Image(systemName: "house.fill")
                }
            SearchView()
                .environmentObject(appData)
                .tag(Tab.search)
                .tabItem {
                    Image(systemName: "magnifyingglass")
                }
            Text("Settings")
                .tag(Tab.settings)
                .tabItem {
                    Image(systemName: "gear")
                }
        }
    }
}
struct Home_Previews: PreviewProvider {
    static var previews: some View {
        Home()
    }
}
// Search View...
struct SearchView: View {
    @EnvironmentObject var appData: AppDataModel
    var body: some View {
        NavigationView {
            List {
                // List of availble coffees.
                ForEach(coffees) { coffee in
                    // Setting tag and selection so that whenever we update selection
                    // that navigation link will be called...
                    NavigationLink(tag: coffee.id, selection: $appData.currentDetailPage) {
                        detailView(coffee: coffee)
                    } label: {
                        HStack(spacing: 15) {
                            Image(coffee.productImage)
                                .resizable()
                                .aspectRatio(contentMode: .fill)
                                .frame(width: 80, height: 80)
                                .cornerRadius(15)
                            VStack(alignment: .leading, spacing: 10) {
                                Text(coffee.title)
                                    .font(.title2.bold())
                                    .foregroundColor(.primary)
                                Text(coffee.productPrice)
                                    .font(.callout)
                                    .fontWeight(.semibold)
                                    .foregroundColor(.gray)
                            }
                        }
                    }
                }
            }
            .navigationTitle("Search")
            // to show demo how it works...
//            .toolbar {
//                Button("GOTO NAV LINK 3") {
//                    appData.currentDetailPage = coffees[2].id
//                }
//            }
        }
    }
    // Detail View...
    @ViewBuilder
    func detailView(coffee: Coffee) -> some View {
        ScrollView(.vertical, showsIndicators: false) {
            VStack {
                Image(coffee.productImage)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: UIScreen.main.bounds.width, height: 200)
                    .cornerRadius(0)
                VStack(alignment: .leading, spacing: 12) {
                    Text(coffee.title)
                        .font(.title.bold())
                        .foregroundColor(.primary)
                    Text(coffee.productPrice)
                        .fontWeight(.semibold)
                        .foregroundColor(.gray)
                    Text(coffee.description)
                        .multilineTextAlignment(.leading)
                }
                .padding()
            }
        }
        .navigationTitle(coffee.title)
        .navigationBarTitleDisplayMode(.inline)
    }
}
 
GitHub
View Github