Last active
April 22, 2021 07:38
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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