How to customize MCBrowserViewController in swift for macOS? - swift

Currently I browse a session using the following:
let mcBrowser = MCBrowserViewController(serviceType: "service", session: p2pSession)
mcBrowser.delegate = self
mcBrowser.maximumNumberOfPeers = 1
listVC.presentAsModalWindow(mcBrowser)
Which produces a view:
I want to know if there's way to customize the appearance of the view controller before it's presented? For instance change the back ground of the list view to be dark instead of white. Or perhaps add an additional button to the window.

Related

UIButton configuration does not update the button title

Recently I've started to run into an issue with UIButton.Configuration API available starting from iOS 15 on a project targeting lower iOS versions. I have a UIButton added using Interface Builder, and for the sake of clearly showing this issue I gave it "This is button title set from Interface Builder" title. In my view controller I have the following code which updates title of the button:
class ViewController: UIViewController {
#IBOutlet private var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 15, *) {
var configuration = UIButton.Configuration.borderless()
configuration.title = "This is button title set programmatically"
button.configuration = configuration
} else {
button.setTitle("This is button title set programmatically", for: .normal)
}
}
}
It does update title of the button, but as soon as I touch it, title changes back to "This is button title set from Interface Builder". Furthermore, if I set button "Style" property in Interface Builder to "Default" rather than "Plain", it starts to completely ignore whatever value I set to configuration.title. Debugging shows that assigned button configuration does indeed have that updated title, but it is completely different from what it renders on the screen:
(lldb) po button.configuration?.title
โ–ฟ Optional<String>
- some : "This is button title set programmatically"
This what button title jumping back to the value from Interface Builder looks like:
And this is how the button is configured in Interface Builder:
The only fix I found so far is to update the title of this button inside of a configuration update handler, like this:
var configuration = UIButton.Configuration.borderless()
...
button.configuration = configuration
button.configurationUpdateHandler = { button in
button.configuration?.title = "This is button title set programmatically"
}
The question is do I really need to have a configuration update handler, if I only want my button to have the same title for different control states, or is it a known bug?
To me it seems really unnecessary to add it if I'm only going to have one title for other states as well.
The problem is that you have put your app into an inconsistent state. If this app is supposed to run on iOS 14, you cannot use the Plain button configuration in Interface Builder, as the iOS 14 device will have no idea what on earth to make of that and you'll crash.
What you need to do is set the interface builder button as a Default button and then, if you find you're running on iOS 15 or later, rip the button right out of the interface and replace it with a configuration-based button, along these lines:
var configuration = UIButton.Configuration.borderless()
configuration.title = "This is button title set programmatically"
let newButton = UIButton(configuration: configuration)
newButton.frame = button.frame
button.removeFromSuperview()
button = newButton
self.view.addSubview(button)
Either that or just give up on trying to use button configurations in a project intended to support iOS 14. Instead, just stick to old-fashioned setTitle(_:for:), etc.
Or else stop trying to support iOS 14 entirely.
In other words: Don't use button configurations at all until the only systems your app runs are systems that actually support button configurations.

How can I hide title bar in SwiftUI? (for MacOS app)

there ๐Ÿ‘‹
I know hide title bar in Storyboard.
But I can't find the way in SwiftUI.
I want to hide title bar with control buttons and make floating image view.
Let me know please.
If you know related example, tell me please.
My little english sorry.. ๐Ÿ™‡
import SwiftUI
#main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}.windowStyle(HiddenTitleBarWindowStyle())
}
}
try HiddenTitleBarWindowStyle()
Removing the Title Bar in Your Mac App Built with Mac Catalyst
Display content that fills the entire height of a window by removing the title bar.
By default, Mac apps built with Mac Catalyst display a title bar across the top of their windows. A horizontal line separates the title bar from the content of the window.
Some Mac apps such as Messages and Contacts have no title bar in their main window. Instead, the top of the window shows only the Close, Minimize, and Zoom buttons with no separator between them and the window's content. In this UI design, the content area fills the entire height of the window.
The following image illustrates these styles in two windows. The first window displays a title bar, while the second has none.
Screenshot of two windows, one stacked above the other, with a dark background in the content area of each window.
Remove the Title Bar
If you choose to design your window without a title bar, you must remove it from the window. To remove the title bar, set the title barโ€™s titleVisibility property to UITitlebarTitleVisibility.hidden and the toolbar property to nil. The following code shows how to remove the title bar and its separator from the window during the setup of a new scene.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
#if targetEnvironment(macCatalyst)
if let titlebar = windowScene.titlebar {
titlebar.titleVisibility = .hidden
titlebar.toolbar = nil
}
#endif
}
Click here for more information
I could not find a way to hide the toolbar entirely in SwiftUI. But this is a possible workaround. You can put this code in your AppDelegate file.
func applicationDidFinishLaunching(_ aNotification: Notification) {
let window = NSApplication.shared.windows.first!
window.titlebarAppearsTransparent = true
window.backgroundColor = .white
window.standardWindowButton(.closeButton)!.isHidden = true
window.standardWindowButton(.miniaturizeButton)!.isHidden = true
window.standardWindowButton(.zoomButton)!.isHidden = true
}
Using this code will make it appear that the toolbar is hidden when in reality, it is still there. But the buttons are hidden, and the background is transparent.

How can i set master/detail view side by side in portrait mode using uisplitviewcontroller

I am using the new UISplitViewController, coming with iOS 14 as follows:
let splitViewController = UISplitViewController(style: .doubleColumn)
splitViewController.preferredDisplayMode = .oneBesideSecondary
let primaryVC = PrimaryViewController()
splitViewController.setViewController(primaryVC, for: .primary)
let secondaryVC = SecondaryViewController()
splitViewController.setViewController(secondaryVC, for: .secondary)
It works as expected, but i wanted to get a similiar result like this:
Landscape
i want to only have a expand icon in the secondaryViewController to hide or show the sidebar as you maybe also know from the Apple Notes App for iPad. I want to hide/remove default Sidebar Icon.
Portrait
i want the primary and secondary view side-by-side. With the new UISplitViewController, the primary view always collapsed and you get a "Back" Button in the NavigationBar.
So is there a way to manipulate or customize the new UISplitViewController to get the result, as i described above?
What i tried
switch to the "classic" UISplitViewController like this:
let splitViewController = UISplitViewController(style: .unspecified)
but with the style unspecified i get the following runtime error:
API misuse. -initWithStyle: may not be used with UISplitViewControllerStyleUnspecified
I think that in your case the style should be doubleColumn, as it's what you want to achieve in both portrait and landscape mode.
Try to implement this method in the UISplitViewControllerDelegate:
optional func splitViewController(_ splitViewController: UISplitViewController,
collapseSecondary secondaryViewController: UIViewController,
onto primaryViewController: UIViewController) -> Bool
And if not already set, set your UISplitViewController's delegate. Return false if you don't want to collapse the split view controller (which means that if not collapsed, it will display two columns; Which is your case).

How to keep NSWindow.FrameAutosaveName out of scope of tabbed windows?

I have a NSWindowControllerclass in an app that can be used to show a standalone window or to show a tabbed window attached to a main window, which has a different window controller. If the user opens the window as standalone, then I want to use the same window position and size as the last standalone window session. It's comparable to opening a code view in Xcode in a new window.
So I have a self.windowFrameAutosaveName = NSWindow.FrameAutosaveName("Detail App Window") line in windowDidLoad. This works, but the problem is that it also works when the window is shown as a tab in the main window. Next time the user opens the same window as standalone, the size of the main window is being used.
Question: how can I keep self.windowFrameAutosaveName outside a tabbed window scenario?
I create the window controller like this:
let storyboard = NSStoryboard(name: "Detail", bundle: nil)
if let controller = storyboard.instantiateInitialController() as? DetailController {
document.addWindowController(controller)
if tabbed,
let mainWindow = document.windowControllers.first?.window,
let detailWindow = controller.window {
mainWindow.addTabbedWindow(detailWindow, ordered: .above)
}
else {
controller.showWindow(nil)
}
}
The code in windowDidLoad of the DetailController above is:
override func windowDidLoad() {
super.windowDidLoad()
self.shouldCascadeWindows = true
self.windowFrameAutosaveName = NSWindow.FrameAutosaveName("Detail App Window")
}
As you see, I use self.shouldCascadeWindows = true, and this must also keep working. I have experimented with detecting being in a tab scenario, but without any complete success. Also, moving the windowFrameAutosaveName before the controller.showWindow(nil) works in itself, but the windows are no longer loaded with shouldCascadeWindows = true.
Interesting, even Xcode doesn't do that, so maybe it's a limitation of AppKit.

UITabBarController customisation page top bar colour swift

How do I change the colour of the top bar of the customisation page of the more view controller. Please see the linked image. Sorry I can't post image here because of my low reputation.
Screenshot Image
Edited with more info:
I have managed to change the background color using the following code. But cant change the color of the top bar.
func tabBarController(tabBarController: UITabBarController, willBeginCustomizingViewControllers viewControllers: [AnyObject]) {
var editView : UIView = tabBarController.view.subviews[1] as! UIView
editView.backgroundColor = UIColor.blackColor()
}
Basically 2 Ways you can achieve this if you are using Global Unique colour in the app for All navigation bar
Use this Solution on App Launch:
UINavigationBar.appearance().barTintColor = UIColor.redColor()
Or if you want to change the Color of More navigationcontroller only then
Use this Solution by getting the Tabbar Reference :
self.tabBarController?.moreNavigationController.navigationBar.barTintColor = UIColor.greenColor()
You can use second solution in the First viewcontroller of the Tab, because that contains your tabbar reference