Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Change Mac Catalyst SwiftUI app UISplitViewController background style to sidebar as in native Mac SwiftUI app
// Apple Forum Question
// 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
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
#if targetEnvironment(macCatalyst)
let dispatchTime: DispatchTime = + 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment