NEW: Learn to build the incredible iOS 15 Weather app today! >>

What's the principle behind the different treatment of titlebarAppearsTransparent and isMovableByWindowBackground?

Forums > SwiftUI

I'm working my way through "Hacking with macOS -- SwiftUI Edition 2020-01-31". One of the projects does some stuff with AppDelegate. Yesterday I asked how to do it with SwiftUI instead of AppDelegate, and the answer was a strange half-and-half thing. Specifically, the project says do the following in AppDelegate:

window.titlebarAppearsTransparent = true
window.isMovableByWindowBackground = true

The SwiftUI way to do this:

// isMovableByWindowBackground is set here in the AppDelegate

class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        guard let app = notification.object as? NSApplication else {
            fatalError("no application object")
        }

        app.windows.first?.isMovableByWindowBackground = true
    }
}

// titlebarAppearsTransparent is now a view that goes into .windowStyle()

@main
struct Project2App: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .windowStyle(HiddenTitleBarWindowStyle())
    }
}

So my question is, why the different treatment of the two different flags? What deep principle (if any) can I learn from it? Cheers

   

I don't think there is any principle beyond "Apple created a modifier for one of those things but not the other."

1      

So my question is, why the different treatment of the two different flags? What deep principle (if any) can I learn from it?

Adding to @rooster, I think you might be seeing the evolution of Swift.

There are many SwiftUI features that were just missing from the earlier versions. Somehow it seemed damnable to release SwiftUI with such blatant holes. To bridge the gap, programmers had to use funky means to wrap UIKit code in ways that could be used in a Swift project. Paul and others had great tutorials on just how to do this with protocols with fun names like UIViewRepresentable.

However, many of these are not needed anymore. Recent changes have eliminated the need for bridge code because features have been brought directly into Swift. Still others stubbornly hang around. Looking directly at YOU CGFloat.

Is this what's happening in your code?

I see references to NSObject and NSApplicationDelegate. This feels very much like bridge code to me. I don't have a crystal ball, but I'd think these and other UIKit remnants will be identified, prioritized, then eventually made more Swifty. Stay tuned!

   

Still others stubbornly hang around. Looking directly at YOU CGFloat.

Which, in Swift 5.5, can be interchanged with Double.

But, yeah, @Obelix pretty much has the right of it. SwiftUI is only two years old, after all, and there is simply no way Apple could have addressed everything from UIKit and AppKit from the beginning. If they had waited until they had everything covered, we still wouldn't have SwiftUI to this day. Instead, they covered a lot of the more common stuff while also providing us a way to bridge with the older frameworks for stuff they haven't gotten to yet. As SwiftUI evolves, more and more stuff will no doubt be ported over.

As for the two properties in question, I would venture to guess that having a titlebar-less window is far more common than having a window that can be moved by grabbing it anywhere within the window bounds. That probably informed their decision to provide a modifer for one but not the other. But only Apple knows for sure.

1      

If you must have isMovableByWindowBackground as a modifer (because it looks cleaner or whatever), I present to you:

extension Scene {
    func movableByBackground(_ movable: Bool) -> some Scene {
        NSApplication.shared.windows.first?.isMovableByWindowBackground = movable
        return self
    }
}

@main
struct Project2App: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .windowStyle(HiddenTitleBarWindowStyle())
        .movableByBackground(true)
    }
}

1      

@roosterboy these principles are plenty deep for me. The historical aspect, the apparent design difference left over from the olden days, learning totally by accident that I don't have to use CGFloat any more, topped all with the first custom modifier that I've ever understood well enough to apply it in my own work. Thanks much, also @Obelix

   

I wrote:

Still others stubbornly hang around. Looking directly at YOU CGFloat.

@rooster wrote:

Which, in Swift 5.5, can be interchanged with Double.

I respond: Not so fast! Looking directly at YOU

func inset(by amount: CGFloat) -> InsettableShape {
      var arc = self
      arc.insetAmount += amount
      return arc
 }

See Drawing SwiftUI Tutorial 3/10

Minute 4:36

   

Hacking with Swift is sponsored by Sentry

SPONSORED With Sentry’s error and performance monitoring for iOS, you see mobile vitals that actually matter, can solve any latency issues quickly, and learn how each release is performing over time.

Learn More

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.