Catalyst Sidebar

in this article from applethey post the following code, which they tout will give you a native sidebar look and feel. however when i add this code to my app delegate i get the error, "Use of unresolved identifier 'window'". I found a window variable in the scenedelage but not the appdelegate. did they change something after writting this article? If so how do i resolve this?


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

  let splitViewController = window!.rootViewController as! UISplitViewController
  let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
  navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
   
  // Add a translucent background to the primary view controller.
  splitViewController.primaryBackgroundStyle = .sidebar
   
  splitViewController.delegate = self
   
  return true
}

ok i think i solved that problem, i put the code in the scenedelegate not the app delegate and i dont get the error anymore. problem is that now i do not know how to actually implement a sidebar in a catalyst master/detail view using the uisplitviewcontroller? I could not find any tutorial on this and the apple article stopped at the .sidebar setting.


So how do i implement a master/detail with sidebar in swiftui for catalyst?

You can modify internal UISplitViewController instance created by SwiftUI by yourself. But it is not good choice, because app not looks like as true macOS app and modified behaviour can be reseted by system at any time. I think that creating a new macOS target as wrapper for your common SwiftUI code is better solution.

You can freely use this snippet:

Code Block swift
//
// SceneDelegate.swift
//
// Created by Egor Merkushev on 11.07.2020.
// Copyright © 2020 Egor Merkushev. All rights reserved.
//
import UIKit
import SwiftUI
import CoreData
extension UIView {
func findViews<T: UIView>(subclassOf: T.Type) -> [T] {
return recursiveSubviews.compactMap { $0 as? T }
}
var recursiveSubviews: [UIView] {
return subviews + subviews.flatMap { $0.recursiveSubviews }
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
public static func vc<T: UIViewController>(vcKind: T.Type? = nil, window: UIWindow?) -> T? {
if let vc = window?.rootViewController as? T {
return vc
} else if let vc = window?.rootViewController?.presentedViewController as? T {
return vc
} else if let vc = window?.rootViewController?.children {
return vc.lazy.compactMap { $0 as? T }.first
}
return nil
}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Get the managed object context from the shared persistent container.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// Create the SwiftUI view and set the context as the value for the managedObjectContext environment keyPath.
// Add `@Environment(\.managedObjectContext)` in the views that will need the context.
let contentView = ContentView().environment(\.managedObjectContext, context)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
// hide title bar for macOS
#if targetEnvironment(macCatalyst)
if let titlebar = windowScene.titlebar {
titlebar.titleVisibility = .hidden
titlebar.toolbar = nil
}
#endif
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
let dispatchTime: DispatchTime = DispatchTime.now() + Double(Int64(0.1 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: dispatchTime, execute: {
let vc = type(of: self).vc(vcKind: UISplitViewController.self, window: window)
if let split = vc {
split.primaryBackgroundStyle = .sidebar // this line changes style and adds visual effect with blur
if let sidebarController = split.viewControllers.first {
sidebarController.view.recursiveSubviews.forEach { (view) in
if view.backgroundColor != nil {
view.backgroundColor = .clear // aggressively makes all opaque views transparent, you can change it to fix only hosting view of SwiftUI in this sidebar controller
}
}
}
}
})
}
}
...

Result you can see here
https://sun9-4 .userapi.com /CVTwqArD-9K-4JeFZOdaLjOFqH2Tkcq0puikPw/Cvt0PEItH8Y.jpg
Catalyst Sidebar
 
 
Q