Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Dezy

macrumors newbie
Original poster
Jul 13, 2021
22
0
I've just begun learning swiftui and I'm trying to make a macos app but I'm very confused. So I have some questions.....

1: What is the correct way to change the size of a window?

Swift:
ZStack() {
Rectangle()
.fill(Color.yellow)
.frame(width: 800, height: 400)

Is this how I should be doing it? If so, do developers then simply add other things like a label and button on top of this rectangle?

2: Where is the listbox?

I just need a listbox that I add items to and then the user clicks on an item.

Swift:
List {
Text("Item 1")
Text("Item 2")
Text("Items 3")
}

I found this code but the only examples I can find are ios examples and nothing that I try to make the items clickable works in my macos app. Should I be using something else?

3: Where are all the macos swiftui tutorials?

It seems that 99% of the swiftui tutorials are for ios. Am I missing something? Some ios code doesn't work in my macos app, or have I got that wrong?

4: Where are the simple tutorials on the Apple website?

Where’s the Apple web page that gives you a list of links that are ‘How to’ instructions? For example…..

How to add a button to a macos app.
How to add a menu to a macos app.
How to add a background color to a macos app’s window.

Thanks for looking at my post!
 
1: What is the correct way to change the size of a window?
In programming I wouldn't necessarily say there's *one* "correct" way. There's typically several correct ways of achieving a goal. My recommendation is this
1626356653965.png

- As you can see it is performed on the outer App layer for the window group itself, not inside the content's view.
Setting it with these parameters spawns the window in the centre of the screen. The user can resize the window, but never less than 1920 and never greater than 3840 (width - see code for corresponding height). You can adjust the frame with other sets of parameters as well
2: Where is the listbox?
I found this code but the only examples I can find are ios examples and nothing that I try to make the items clickable works in my macos app. Should I be using something else?
I assume what you want is just to add Button objects to your List view. Either just replacing your Text entries in the list with Button objects, or creating Stacks for each entry in the list with a static text label and a button.
3: Where are all the macos swiftui tutorials?
iOS has a much much larger user base. There's just less focus on the Mac. But fortunately, most SwiftUI code is very cross platform. While there are significant differences, most of the information you find for iOS will be true for macOS too. And needing to fiddle with something rather than just copying tutorial code is good for learning anyway. So I think it can be OK that the tutorials you look at don't apply 100% anyway :)
4: Where are the simple tutorials on the Apple website?
Open Xcode, hit the Help button in the menu bar, hit Developer Documentation. There are loads of pages there. You can select SwiftUI on the left for the SwiftUI overview page or search for specific structs or classes or whatever in the top bar. It is still somewhat iOS focused (though also very generalisable) but here's Apple's own tutorial-form guides
 
casperes1996

1: Thanks for the info and code. It helps me set a good foundation as opposed to setting a foundation on code that I'm not 100% sure of.

2: Button objects, okay.

3: Good, now I know where I stand with Swiftui/Swift. Thanks for clearing that up.

4: I was too busy looking at websites that I forgot about Help so I quickly used it/searched for List and there's some good information there. But I will say that apple's documentation on its website could certainly be more user friendly.

szymczyk

Thanks for the link/video. “The journey of making a Mac app in SwiftUI” on that website looks good too.

Thanks for replying guys :)
 
1: Thanks for the info and code. It helps me set a good foundation as opposed to setting a foundation on code that I'm not 100% sure of.
3: Good, now I know where I stand with Swiftui/Swift. Thanks for clearing that up.
You're very welcome :)
4: I was too busy looking at websites that I forgot about Help so I quickly used it/searched for List and there's some good information there. But I will say that apple's documentation on its website could certainly be more user friendly.
Sure. While they have some more beginner oriented SwiftUI tutorials, Apple's docs are more aimed at programmers with existing experience on developing for Apple wanting information on a framework or whatever, but already knowing a lot of other things. Frankly I rarely use the website cause I tend to just use the Xcode developer doc viewer, though the same info is available on developer.apple.com. Apple's own documentation varies a lot. Sometimes it's incredibly well written and super helpful, sometimes not so much.

In my opinion the best learning resource for SwiftUI (and really any Swift topic) is Paul Hudson and his HackinWithSwift series (YouTube and books). I didn't mention it earlier though because while also generally applicable and occasionally with some Mac specific stuff, it is still mostly iOS focused
 
Yes it seems odd that Apple doesn't do more for new developers but then I guess, when you're a trillion dollar company, catering to these people (some of whom will give up) isn't a priority. And so we have people like Paul Hudson picking up the pieces. He appears a lot in my search results so yes, now that he has your endorsement, I'll spend more time/effort looking at his website/youtube clips.

Thanks again!
 
Yes it seems odd that Apple doesn't do more for new developers but then I guess, when you're a trillion dollar company, catering to these people (some of whom will give up) isn't a priority. And so we have people like Paul Hudson picking up the pieces. He appears a lot in my search results so yes, now that he has your endorsement, I'll spend more time/effort looking at his website/youtube clips.

Thanks again!

I don't know Apple actually does a lot that's just not directly them. Apple collaborates with people like Paul Hudson for example. He has Apple's endorsement too for a lot of what he does.
They also have the Swift Playground app for iPadOS which I think is Apple's idea of a starting point. Guess they figure there's already amazing content so no need to make their own as well. And a lot of programmers also come from university courses (though not all of course).

But btw. feel free to reach out to me at any time as well if you want help with anything. Can of course be reached here and if you want faster more direct contact you can Discord me too
Casper#3603
:)
 
  • Like
Reactions: grandM
Well that's good to know. Meanwhile, I'll just carry on learning what I can and maybe things will get easier in the future as a result of Apple's efforts as well as my own efforts.

And thanks for the offer of help, I won't be doing Discord (I had to look it up o_O) but I'm sure I'll be posting here again in the future so I'm confident we'll talk again soon.
 
Well that's good to know. Meanwhile, I'll just carry on learning what I can and maybe things will get easier in the future as a result of Apple's efforts as well as my own efforts.

And thanks for the offer of help, I won't be doing Discord (I had to look it up o_O) but I'm sure I'll be posting here again in the future so I'm confident we'll talk again soon.

Sure thing. Discord’s essentially just a chat app. I enjoy talking and helping folk with code things so I often offer it as an Instant Messaging solution. But I also have the developer forums on email alert so yeah, sure we’ll probably run into each other again regardless :p - In any case good luck with your programming adventure
 
Well it seems we’re not out of the woods just yet. Because when I use this code….

Swift:
@main
struct SwiftUITestingApp: {
var body: some Scene {
WindowGroup {
ContentView().frame(minWidth: 1920, idealWidth: 2560, maxWidth: 3840, minHeight: 1080, idealHeight: 1440, maxHeight: 2880, alignment: center)
}
}
}

I get the error “Cannot find ‘center’ in scope” (I created this problem by not typing your code correctly).

So I inserted a dot like this…. alignment: .center

The error goes away and I start the app. The app starts in the center of the screen. Then I move the window horizontally half way off the screen. Then I stop the app and then I run the app. And then sometimes the app doesn’t start in the center of the screen/it’s in the ‘half way off the screen’ position.

I tried this (because in Help > Developer Documentation > Search > Center > Swiftui it says)…..

center: VerticalAlignment)

I get an error… “Extra argument 'center' in call”

I also tried center() but that also didn’t fix it.

So, any thoughts about how to fix this?
 
Well it seems we’re not out of the woods just yet. Because when I use this code….

Swift:
@main
struct SwiftUITestingApp: {
var body: some Scene {
WindowGroup {
ContentView().frame(minWidth: 1920, idealWidth: 2560, maxWidth: 3840, minHeight: 1080, idealHeight: 1440, maxHeight: 2880, alignment: center)
}
}
}

I get the error “Cannot find ‘center’ in scope” (I created this problem by not typing your code correctly).

So I inserted a dot like this…. alignment: .center

The error goes away and I start the app. The app starts in the center of the screen. Then I move the window horizontally half way off the screen. Then I stop the app and then I run the app. And then sometimes the app doesn’t start in the center of the screen/it’s in the ‘half way off the screen’ position.

I tried this (because in Help > Developer Documentation > Search > Center > Swiftui it says)…..

center: VerticalAlignment)

I get an error… “Extra argument 'center' in call”

I also tried center() but that also didn’t fix it.

So, any thoughts about how to fix this?
OK, so I'm going to break this down a bit. First and foremost though, the dot notation was the correct one and all the behaviour you saw with it was expected and correct. I will show you a way of achieving a fresh entering every time later, but I'm going to do pull back a few steps first. John Mayer once said "My advice is that when you learn something, go back and learn the things that form the foundation for the thing you just learned.

I think it's a good idea to understand a bit more about Swift before you dig deeper with SwiftUI.

Let's look into what .center actually means and why it works.

So the method signature for the frame modifier looks like this
1626445730923.png


As you can see here, the "alignment" parameter takes as input an Alignment. An Alignment can be initiated with separate vertical and horizontal alignments, but has static class variables we can use that define common overall alignments.
When we here just say
.center
what we're actually saying is
Alignment.center
We are accessing the pre-made Alignment object called center. The reason we can omit the Alignment in the beginning is that it is implicitly inferred because the function takes an Alignment. You can try this out for yourself.

Swift:
enum Option {
    case A, B, C
}

func doSomething(what: Option) {
    print(what)
}

doSomething(what: .A)
As you can see, we can call the doSomething function and pass it simply .A, with the Option. being implied.

Now let's talk about the behaviour you're seeing and why you're seeing it.

The center alignment on the frame here does, perhaps confusingly, not refer to the placement of the window itself. It refers to an invisible frame around the content that the window then holds. Changing the alignment will alter the positioning of items within the window, not the placement of the window itself.

Furthermore, macOS, as intended behaviour, stores the location of windows when an application is quit so they can be placed the same location again on reopening for the user. If you close the window and not the app itself it will not be saved.

In AppKit this requires a little bit of work on the developer's side, but SwiftUI has it as default behaviour. In fact, the way SwiftUI is intended to be used you can't really even get the NSWindow object itself without it feeling like a bit of a hack. - SwiftUI is not entirely as feature rich as AppKit yet, so a lot of developers will use SwiftUI where they can but fallback to AppKit/UIKit as necessary.
The following is a pretty good article that describes some ways of working around SwiftUI limitations in the WindowGroup system, but also explains benefits of it


Now. There are two ways I have for you to tackling the particular problem at hand. One of them is more elegant from a SwiftUI point of view (though not entirely), but gives a slightly worse user experience Imo and forces ALL windows to start in the center of the screen and upon an application restart it will only snap the key window (currently active) back to the center.
Now that last point of course isn't a problem if you also intend to limit this to one window (see the linked article - App groups support multiple windows by default)

This is the idea
Swift:
//
//  SwiftUITestingApp.swift
//  SwiftUITesting
//
//  Created by Casper Sørensen on 15/07/2021.
//

import SwiftUI
import AppKit

@main

struct SwiftUITestingApp: App {

    @State private var window: NSWindow?

    var body: some Scene {

        window?.center()

        return WindowGroup {
            ContentView().frame(minWidth: 1920, idealWidth: 2560, maxWidth: 3840, minHeight: 1080, idealHeight: 1440, maxHeight: 2880, alignment: Alignment.center)
                .background(WindowAccessor(window: $window))
        }
    }
}

struct WindowAccessor: NSViewRepresentable {

    @Binding var window: NSWindow?

    func makeNSView(context: Context) -> NSView {

        let view = NSView()

        DispatchQueue.main.async {
            self.window = view.window
        }
        return view
    }

    func updateNSView(_ nsView: NSView, context: Context) {}

Not a lot changes in the App struct, but we need to have a lot of fluff there in the ViewRepresentable to get the window object to center. Also noteworthy is that this code is not cross platform.

The other solution is in my opinion better but the downside is that we'll have to leave the SwiftUI Lifecycle and use the AppKit lifecycle instead. I personally prefer the AppKit lifecycle for now though since SwiftUI doesn't always allow you to tweak everything, so the old AppKit patterns can come in handy and you can always wrap things up to use SwiftUI where appropriate. It looks like this in the AppDelegate:

Swift:
import Cocoa
import SwiftUI

@main
class AppDelegate: NSObject, NSApplicationDelegate {
    var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.

        let contentView = ContentView()

        // Create the window and set the content view.

        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 1920, height: 1080),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)

        window.isReleasedWhenClosed = false
        window.center()
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }
}

In fact this is **almost** Xcode's default AppKit lifecycle SwiftUI project. All I've changed is that I've removed the frameAutoSave line as well as changed the size of the NSWindow that gets created to host the SwiftUI View.

If you want to take this approach I recommend just creating a new Xcode project with the AppKit lifecycle and dumping your SwiftUI files back into that from your current project, as it's easier than setting up a storyboard and AppDelegate yourself.

This way of doing it doesn't have the "snapping" behaviour visible in the prior SwiftUI lifecycle code snippet where you can briefly see the window in its former location before it moves back. It is more AppKit mindset than SwiftUI mindset however, but I couldn't personally find a pure SwiftUI solution to preventing window location autosave and restore. I feel like it ought to work to remove the UserDefaults' key for the window but it seems SwiftUI stores it differently or something. Keep in mind SwiftUI is still a fairly new framework so may not on its own offer all desired functionality. It's primary purpose is making the most common apps easier to make. I guess preventing the system from saving window state hasn't been in the cards for that, so we use some older AppKit behaviour to get it :) - At least that's my solution for it. Others may very well exist - most likely do - but I looked around and couldn't find anything pure and clean SwiftUI
 
Last edited:
Seriously? This is what I have to do (not that I understood a lot of it) to get a window centered when it starts?

What are the Apple developers thinking when they make this stuff?

I don't know C# but here's the code to center the form when it starts.....

C#:
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(parentForm.Width / 2 - form.Width / 2 + parentForm.Location.X,
parentForm.Height / 2 - form.Height / 2 + parentForm.Location.Y);
form.Show();

And if you don't want to code it, you can simply click on the form's alignment properties listbox and select "Center Window" (or whatever it's called).

And that's all there is to it.

Centering a window shouldn't require an IT degree.

Xcode is really starting to suck.
 
What are the Apple developers thinking when they make this stuff?
To be fair, the version I sent that was based on the AppKit lifecycle, in terms of entering on launch, was 1 line different to the starting point of the template. That's hardly a lot. There's only really issues with the WindowGroup version because it's meant for cross-platform use and doesn't intend for you to touch individual windows.
Xcode is really starting to suck.
This isn't really an Xcode thing, n'or a language thing. The comparison to C# doesn't entirely hold as a comparison to C# since you're instead comparing different UI frameworks. You could also write a C# application using some other framework that might also not easily let you touch the window. If you for example were writing a Flutter app you would likely meet very much the same barriers you are with SwiftUI because the framework has different goals

I tried to explain things as I went along but I'm sorry if it was too much all at once. Honestly speaking I do believe Apple's frameworks are some of the nicest and easiest to work with. I encourage you to keep learning. Some things will always be simpler with some tools and SwiftUI is a new framework that really does make most things fairly simple, but just doesn't really have all features yet. The reason all this may have gotten a little complex is that we had to interact with AppKit/Cocoa and didn't stay within SwiftUI. For 99% of the code you write that won't be necessary
 
  • Like
Reactions: 09872738
Firstly, sorry for the rant. I’ve been trying out various IDEs recently and they’ve all had some issues that forced me to look for a better IDE. I finally settle on Xcode and then, surprise surprise, this IDE also has an issue! But… That’s no excuse for me to rant unjustifiably. In fact, upon reflection, the real problem is me. I expect the IDE to be perfect. And that’s quite a naive approach when I think about it. So….. Lesson learnt.

Secondly, thank you casperes1996 for going to all that trouble to explain/code a thorough reply. I have re-read it and I understood a little bit more of it. So that’s good. And I can appreciate that coding is a difficult topic to explain, especially to a newbie, so I do appreciate your effort.

Finally, let me get back to this window problem. There’s good news….

I spent some time trying to work out why this problem was occurring. But I couldn’t recreate the problem. In other words, regardless of what I did, when I closed or quit the app and then started it again, the window would always be entirely visible on the screen. So, whatever was causing this problem has gone away. And you know what? For now, that’s good enough for me. So I will consider this case closed.

Thanks guys :)
 
Firstly, sorry for the rant. I’ve been trying out various IDEs recently and they’ve all had some issues that forced me to look for a better IDE. I finally settle on Xcode and then, surprise surprise, this IDE also has an issue! But… That’s no excuse for me to rant unjustifiably. In fact, upon reflection, the real problem is me. I expect the IDE to be perfect. And that’s quite a naive approach when I think about it. So….. Lesson learnt.
Ey, no worries. Though I think you may be thinking more about language/framework than IDE? Xcode can also be used to write C, C++, Objective-C - From a code perspective the experience will be very different, but the IDE and the tools only pertaining to it will (for the most part at least) be identical since it's still Xcode. This may of course be what you mean, I'm just thinking you might mean language/framework more so than IDE based on prior post :) It may seem like an academic difference, since most folk who write a certain language often use a specific IDE, but you could write Swift and SwiftUI programs in Visual Studio Code or a JetBrains IDE too.
Secondly, thank you casperes1996 for going to all that trouble to explain/code a thorough reply. I have re-read it and I understood a little bit more of it. So that’s good. And I can appreciate that coding is a difficult topic to explain, especially to a newbie, so I do appreciate your effort.
Ey, no worries. Happy tp help where I can. If you want me to try and explain anything more or in a different way I'll gladly do that as well. I often advice that people do not try and learn Swift, or SwiftUI or Java or app development or anything concrete like that, instead initially focus on learning "programming". I see the distinction a bit like learning to use a hammer versus learning to be a carpenter. Or perhaps an even better analogy, learning piano versus learning music. One might involve the other but comprehensive understanding of music theory will make you a better pianist, though theoretical knowledge alone will not make you a great pianist. Understanding music will make it easier to read sheet music, understand the musical intent and apply concepts you see in different context to perhaps create your own solos or better parttake in freeform jazz or something.
It takes anybody a lot of time to really master a language, its culture, expectations and best practices, but I would argue that if you're a good programmer who knows all the fundamental stuff that builds a language, you can pick up most languages well enough to write programs with them in a very very short amount of time.
I've written an OS in C/x86-64 assembly, distributed server code in Go, file structure generators in Python, apps in Java and Swift, game logic in C#, a compiler in OCaml - the point here is not to list a resumé, but instead to say that I wouldn't really call myself an expert in any of these though I am probably the closest with Swift; But I know enough fundamental material that I can be given a task in a language I've never seen before and fairly quickly finish the task. I was given a university assignment about half a year ago to write the so-called Simplex algorithm using various different pivotting rules in Python. It's not important that you know the algorithm, it was just code I needed to write. Prior to that I had written about 15 lines of Python. But it didn't really matter cause I knew what I needed to solve my problem and I knew how to find the building blocks I needed to build it with Python.
And long story short that's why I recommend people focus more on understanding and learning fundamentals when they start out than language syntax and semantics :) - And sticking with a toolchain for some time. Before uni, I spent way too long jumping between languages and such myself
I spent some time trying to work out why this problem was occurring. But I couldn’t recreate the problem. In other words, regardless of what I did, when I closed or quit the app and then started it again, the window would always be entirely visible on the screen. So, whatever was causing this problem has gone away. And you know what? For now, that’s good enough for me. So I will consider this case closed.
Oh yeah, so I may have slightly misunderstood something earlier - The intended behaviour is that the window should reopen where it was quit, but if part of the window was outside the screen border it should be in the nearest position whole within the screen frame. If it stayed outside the screen's frame that sounds like an odd mishap with macOS' display server or something, I dunno.
 
xStep thanks for replying. Just one thing though, the link isn't working when I click on it.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.