Skip to content

Instantly share code, notes, and snippets.

@SoundBlaster
Last active April 22, 2021 07:38
Show Gist options
  • Save SoundBlaster/05362e2ee026a524f2489483edcb777d to your computer and use it in GitHub Desktop.
Save SoundBlaster/05362e2ee026a524f2489483edcb777d to your computer and use it in GitHub Desktop.
Change Mac Catalyst SwiftUI app UISplitViewController background style to sidebar as in native Mac SwiftUI app
// Apple Forum Question https://developer.apple.com/forums/thread/129211?answerId=620460022#620460022
//
// 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()
#if targetEnvironment(macCatalyst)
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
}
}
}
}
})
#endif
}
}
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment