Swift / Apple Development Chat

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
Since a couple of us keep getting sidetracked discussing development in Swift or on Apple platforms, maybe we can do some of it here? A place to post questions, neat learnings, complaints, etc to share with others without sidetracking other threads on it?

Maybe I can start by saying: SwiftUI, you are drunk, go home. When you attach a context menu to a view, if it happens to be a button (NavigationLink in this case), it replicates the button's state at the time instead of rendering the button content. But if I attach the context view to the content, the button can swallow the gesture and prevent the context menu from working unless you are on macOS. Great times. Great times. I suspect I'm going to have to drop down to UIKit to get behavior I like on this one. :(


IMG_0022.PNG
 

Cmaier

Site Master
Staff Member
Site Donor
Posts
5,086
Reaction score
8,007
Yikes.

I use SwiftUI (so far) only in discrete views, and particularly in certain views that have tables views in them. Mostly because it’s so much easier to make each table row have a different ad hoc layout in SwiftUI than it is in UIKit. There are still just too many limitations for me to use SwiftUI for anything more complicated than that.
 

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
Yikes.

I use SwiftUI (so far) only in discrete views, and particularly in certain views that have tables views in them. Mostly because it’s so much easier to make each table row have a different ad hoc layout in SwiftUI than it is in UIKit. There are still just too many limitations for me to use SwiftUI for anything more complicated than that.
I've been building an app from scratch in SwiftUI since late last year in my spare time, and it's gotten far enough along that it's time to starting pushing towards a beta/release. So far I've managed to limit how often I drop down to AppKit/UIKit, but there's still some utterly bizarre things that just don't work right in SwiftUI.

If SwiftUI let you specify a preview view for a context menu, this would take me all of 5 seconds to fix, but it doesn't. So instead I have to drop down to UIKit and expose out the context preview myself.
 

MEJHarrison

Site Champ
Posts
839
Reaction score
1,633
Location
Beaverton, OR
I like to tinker with SwiftUI. I usually get hyped up around WWDC, play with it for a month or two and then move on. I skipped last year because I was into VR at the time. But this year, I'm expecting my new Mac to be here by then. That's going to be a blast. Xcode is just too annoying on my old Mac. It seems like it's 10-15 minutes by the time I get Xcode going, my project loaded, my project building, etc.. I suspect the new M1 will make a world of difference in that regard. So I plan to dive back in head first come June.

My biggest problem is I need a project, or it's just playing around. But I have no good ideas. The last application I wanted I've already turned into a Mac app. I just need a good idea. Not so much for sale (though that would be cool). Just enough to keep me interested and give me a good reason to keep working out the problems. Otherwise I'll be bored a month later and on to the next interest.
 

MEJHarrison

Site Champ
Posts
839
Reaction score
1,633
Location
Beaverton, OR
Since we're talking about SwiftUI, does anyone have good resources? I've been a fan of the stuff from Mark Moeykens from Big Mountain Studio. But it's 100% encyclopedic, not "let's learn SwiftUI". Still, if you like a good reference, it's fantastic. In addition to getting "the book", you get the whole thing as an Xcode project as well. So you could find that "page" in the project and play with real working code. I'll attach a screenshot if you're curious. I have found it to be quite complete and he updates them throughout the year. The only downside is you're buying a single version of the book. When he updates the books for all the new stuff this year, it will be a new purchase (with a discount). All his books are also on sale this week, so if you're interested, it's the perfect time to get something that will be outdated in a month.

What other resources do people use? Since it's been a couple years, I wouldn't be opposed to something that's more teaching than reference.

Here's a screenshot of the project that goes with the SwiftUI Mastery book. This is the source code for the actual book. I tried to get the preview going, but after playing with it for 15 minutes, I finally gave up. Can't wait for my new Mac. :ROFLMAO:

Screen Shot 2022-05-02 at 5.33.21 PM.png
 

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
I’m a bit all over the place with how I’ve picked up SwiftUI. Partly because I’m too cheap to actually pay for a good resource, and there‘s a lot of “here‘s the basics” and not enough “here’s how to build something substantial with the framework” out there, IMO.

That said, I think the most helpful stuff for me has been the random videos on YouTube where someone replicates some specific bit of UI in SwiftUI. It’s mostly replicating some of the slicker animations Apple does in their apps, but it’s useful for understanding just how to describe some of these more detailed components within SwiftUI. But it probably is best if you have a working understanding first as some channels like kavsoft don’t do any explanation of the code, just demonstration of the code step-by-step.

I’d love a resource that’s aimed at demonstrating how to scale SwiftUI up, looking at good vs bad patterns. At this rate, if I ship this project, my next project might have to be writing up what I’ve learned about SwiftUI and the bad patterns I’ve had to keep fixing to avoid painting myself in a corner. There’s a couple folks who have written up their thoughts, but one boiled down to “I used a massive Observable Object thinking it would work like a Redux Store, invaliding my whole view hierarchy on every state change, and my performance sucked, so I’m trying to avoid Observable Object going forward.“ While I’m over here watching them throw the baby out with the bath water. But getting good performance is tricky. It’s easy to over-observe state as you try to refactor things to get better composition.

(It probably doesn’t help that I’m a bit of a MVVM noob and have been making mistakes that I then need to clean up on that front too. I’m in the middle of making it easier to compose model objects into a single view model rather than trying to compose multiple view models into a view)
 

MEJHarrison

Site Champ
Posts
839
Reaction score
1,633
Location
Beaverton, OR
I’m a bit all over the place with how I’ve picked up SwiftUI. Partly because I’m too cheap to actually pay for a good resource, and there‘s a lot of “here‘s the basics” and not enough “here’s how to build something substantial with the framework” out there, IMO.

Apple themselves are the worst at that. Their stuff is very flashy and designed to perfectly fit SwiftUI. I don't find their demos to be super great real-world examples.

That said, I think the most helpful stuff for me has been the random videos on YouTube where someone replicates some specific bit of UI in SwiftUI. It’s mostly replicating some of the slicker animations Apple does in their apps, but it’s useful for understanding just how to describe some of these more detailed components within SwiftUI. But it probably is best if you have a working understanding first as some channels like kavsoft don’t do any explanation of the code, just demonstration of the code step-by-step.

Interesting... I'd not thought of that. I used to prefer reading, but have gotten more into YouTube this past year. I might have to check that out.
 

Andropov

Site Champ
Posts
593
Reaction score
725
Location
Spain
Heh. I changed jobs in February and my new employer is all-in on SwiftUI for new developements. So for the last couple months I've been working mostly on SwiftUI only, and for production apps. I used to think it was too soon to use SwiftUI on prod, but they got it working nicely. One thing that I think helps immensely is having flexible design requirements. The worst part of SwiftUI is the edge cases where getting it to match the design is hard or impossible. But you can often just design around it.

A real example comes to mind: an app we're developing had a button on the navigation bar that triggered an action sheet (which is unavailable in SwiftUI, unless you drop down to UIKit) but after talking with the designer, it was agreed that using a pull-down contextual menu was also a good choice. Saved a lot of development effort and IMHO is actually a better choice than the action sheet. Of course, you can't always do this, but not fighting the framework at every step helps a lot.
 

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
Heh. I changed jobs in February and my new employer is all-in on SwiftUI for new developements. So for the last couple months I've been working mostly on SwiftUI only, and for production apps. I used to think it was too soon to use SwiftUI on prod, but they got it working nicely. One thing that I think helps immensely is having flexible design requirements. The worst part of SwiftUI is the edge cases where getting it to match the design is hard or impossible. But you can often just design around it.

Generally good advice when you can follow it. I have had to design around SwiftUI mis-behavior, but sometimes designing around the problem is itself a chore.

I think SwiftUI was ready for production with V1, but for specific cases. Each year has covered more of what UIKit/AppKit can do and I think it's maybe 80% of the way there, which is enough for an awful lot of apps. But if you need a AVRoutePickerView, or a WKWebView, or the like, you have to drop down to UIKit or AppKit. Not much choice when you are rubbing up against the edge cases of the framework.

A real example comes to mind: an app we're developing had a button on the navigation bar that triggered an action sheet (which is unavailable in SwiftUI, unless you drop down to UIKit) but after talking with the designer, it was agreed that using a pull-down contextual menu was also a good choice. Saved a lot of development effort and IMHO is actually a better choice than the action sheet. Of course, you can't always do this, but not fighting the framework at every step helps a lot.

Yeah, for that example, I definitely wouldn't fight the framework. My gripes are more that it seems like Apple is rushing to get coverage done and when they add functionality it's not always really usable as-is, like the context menu screenshot above. Because SwiftUI doesn't fully support the functionality, it's a whole ordeal when you hit bugs like what I've run across. Sidebars on iPad, toolbars on the Mac, focus on Apple TV when using complicated layouts... they all are still pretty buggy in one way or another.
 

Andropov

Site Champ
Posts
593
Reaction score
725
Location
Spain
Generally good advice when you can follow it. I have had to design around SwiftUI mis-behavior, but sometimes designing around the problem is itself a chore.
It definitely depends on how strict the requirements are. For personal projects, where I can freely change the design or drop entire features, I love using SwiftUI. But I've worked at places where design requirements had to be followed to the pixel. Using SwiftUI there would have been a nightmare.

But if you need a AVRoutePickerView, or a WKWebView, or the like, you have to drop down to UIKit or AppKit. Not much choice when you are rubbing up against the edge cases of the framework.
Out of curiosity, what have you been using on macOS? SwiftUI over AppKit or SwiftUI over UIKit using Catalyst? It's kinda awkward that both are possible right now.

Yeah, for that example, I definitely wouldn't fight the framework. My gripes are more that it seems like Apple is rushing to get coverage done and when they add functionality it's not always really usable as-is, like the context menu screenshot above. Because SwiftUI doesn't fully support the functionality, it's a whole ordeal when you hit bugs like what I've run across. Sidebars on iPad, toolbars on the Mac, focus on Apple TV when using complicated layouts... they all are still pretty buggy in one way or another.
The focus engine comes to mind here as well. I gave up trying to implement a CommandGroup whose commands affected only the active window on a multi-scene SwiftUI app on macOS (commands are app-wide so you need a reference to the active View or ViewModel... good luck doing that using the SwiftUI focus API).

I agree that Apple is basically rushing the full API coverage here, but there's no good option here IMHO. I think I'd rather have a buggy API than no API at all, but it's frustrating when you find existing but unusable API, like the context menu bug you found. And if you can't work around the bug, you may end up having to throw away a lot of what you had already done and drop to UIKit.

Thankfully, they're fixing the bugs at a good pace too. I'm sure the buggiest already released APIs will be fixed post-WWDC '22. Last year I saw all the SwiftUI bugs I was seeing in my SwiftUI app (navigation bar related) disappear as soon as I recompiled the app with the Xcode beta. That was beautiful.
 

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
It definitely depends on how strict the requirements are. For personal projects, where I can freely change the design or drop entire features, I love using SwiftUI. But I've worked at places where design requirements had to be followed to the pixel. Using SwiftUI there would have been a nightmare.

Yeah, I’m somewhere in the middle. It’s not so much that I have to do things a specific way, but rather I’d have to depart far away from what people expect in order to avoid certain limitations, so I tend to push through and make it work because so much other stuff is faster to do. I’m not doing anything terribly fancy (yet), but there are things Apple does in their own apps that simply cannot be done in SwiftUI yet, while there’s some really fancy stuff that is quite doable in SwiftUI once you are in the right mindset for it.

To get hover effects working in the Mac toolbar for items taller than 32pt, I made some ugly hacky workarounds that convinced SwiftUI to setup the hover area properly. But at least I didn’t have to drop down to AppKit. But it got me my ”fancy” toolbar control similar to Podcasts/Books/Music.

Context menus I either need to drop down and create my own view modifier and result builder to redescribe the context menu in terms of the UIKit version, or build custom selection/editing views. I might actually go the latter since it enables bulk editing as well.

Out of curiosity, what have you been using on macOS? SwiftUI over AppKit or SwiftUI over UIKit using Catalyst? It's kinda awkward that both are possible right now.
SwiftUI over AppKit. Using Catalyst gets you a functional navigation stack which I could certainly use, but also comes with its own set of issues where things need to be done specifically for Catalyst because it isn’t exactly the same as UIKit. And there are things that AppKit SwiftUI supports but Catalyst does not.

I built a custom navigation stack for AppKit SwiftUI, but it causes havoc with the toolbar that I need to find a clever answer for. I might pull some ideas from the Apple TV interface I’ve been building to do it and just bypass the behavior entirely in favor of something a little different. I’ll just lose the nice translucent effect of the titlebar when used with a scroll bar to do it…

The focus engine comes to mind here as well. I gave up trying to implement a CommandGroup whose commands affected only the active window on a multi-scene SwiftUI app on macOS (commands are app-wide so you need a reference to the active View or ViewModel... good luck doing that using the SwiftUI focus API).

I’m about to bang my head on that particular wall. Let’s see how bad it is.

I agree that Apple is basically rushing the full API coverage here, but there's no good option here IMHO. I think I'd rather have a buggy API than no API at all, but it's frustrating when you find existing but unusable API, like the context menu bug you found. And if you can't work around the bug, you may end up having to throw away a lot of what you had already done and drop to UIKit.

I’ve taken the approach of building specific components and making them SwiftUI-like. It’s not too bad but it is tedious hooking up custom result builders for things.

Thankfully, they're fixing the bugs at a good pace too. I'm sure the buggiest already released APIs will be fixed post-WWDC '22. Last year I saw all the SwiftUI bugs I was seeing in my SwiftUI app (navigation bar related) disappear as soon as I recompiled the app with the Xcode beta. That was beautiful.

That is the good news for sure. The main reason I’ve gotten as far as I have in pure SwiftUI is because of the fixes in SwiftUI 3.
 

Andropov

Site Champ
Posts
593
Reaction score
725
Location
Spain
Yeah, I’m somewhere in the middle. It’s not so much that I have to do things a specific way, but rather I’d have to depart far away from what people expect in order to avoid certain limitations, so I tend to push through and make it work because so much other stuff is faster to do. I’m not doing anything terribly fancy (yet), but there are things Apple does in their own apps that simply cannot be done in SwiftUI yet, while there’s some really fancy stuff that is quite doable in SwiftUI once you are in the right mindset for it.
About the fancy stuff, being able to animate every change you want to so easily is a big plus of SwiftUI. I hope it drives changes on the tools UI/UX designers use so animations become a core part of the design. From what I've seen (Figma files), animations aren't usually specified on the design template (don't know if it's a tool limitation or just that most UI/UX designers are still not used to specifying them, as they used to be costly to implement in code). So it's often left undetermined. Really hope that changes, I believe good (but subtle) animations make an app feel much more polished.

And there are things that AppKit SwiftUI supports but Catalyst does not.
And vice versa 😵‍💫 (don't remember the specifics anymore).
 

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
The focus engine comes to mind here as well. I gave up trying to implement a CommandGroup whose commands affected only the active window on a multi-scene SwiftUI app on macOS (commands are app-wide so you need a reference to the active View or ViewModel... good luck doing that using the SwiftUI focus API).

Aha, so I think I figured this out. The focus engine generally is aimed at keyboard focus for iOS/Mac, or cursor focus on Apple TV. However, focusedSceneValue() is intended to provide this sort of 'first responder' style state information, and then you can observe this state using @FocusedValue in your commands object.

I was able to create a contextual command that is enabled when specific views are visible, and it seems to work well on iPad as well, but iPad seems to have some issues triggering update of state properly in cases where it works on Mac. I'll have to read up a bit more since it seems related to how iPad expects commands to be based on navigation state, rather than other app state (like the state of your underlying model).

And vice versa 😵‍💫 (don't remember the specifics anymore).

Yeah, it's the question: Do you want UIKit-isms or AppKit-isms?
 

Andropov

Site Champ
Posts
593
Reaction score
725
Location
Spain
Aha, so I think I figured this out. The focus engine generally is aimed at keyboard focus for iOS/Mac, or cursor focus on Apple TV. However, focusedSceneValue() is intended to provide this sort of 'first responder' style state information, and then you can observe this state using @FocusedValue in your commands object.

I was able to create a contextual command that is enabled when specific views are visible, and it seems to work well on iPad as well, but iPad seems to have some issues triggering update of state properly in cases where it works on Mac. I'll have to read up a bit more since it seems related to how iPad expects commands to be based on navigation state, rather than other app state (like the state of your underlying model).
I'm doing exactly that, but the FocusedValues property setter for my @FocusedValue object is not called when I click on a different window. It gets called if I press 'tab' (which controls keyboard focus, so I'm guessing that's why it works) or if I create a new scene, but that's about it.
It's particularly frustrating because I mostly did the command things for macOS, where there used to be this very simple concept of the 'keyWindow', literally *the window that receives the keys*. But it got screwed over due to the new iPadOS multitasking model. Now an app can have multiple key windows (one per scene), but there's no 'keyScene' property to find which scene is actually receiving the keys. So I can't reliably retrieve the true keyWindow, even if the windows themselves are clearly calling makeKeyAndVisible reliably because I see the semaphore in the window bar change colors.

If you got it working on Mac but it doesn't always fire on iPad, maybe I'm not getting it to work on macOS because I'm using Catalyst. I'll test my app on iPad to see how badly it works there.
 

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
I'm doing exactly that, but the FocusedValues property setter for my @FocusedValue object is not called when I click on a different window. It gets called if I press 'tab' (which controls keyboard focus, so I'm guessing that's why it works) or if I create a new scene, but that's about it.
It's particularly frustrating because I mostly did the command things for macOS, where there used to be this very simple concept of the 'keyWindow', literally *the window that receives the keys*. But it got screwed over due to the new iPadOS multitasking model. Now an app can have multiple key windows (one per scene), but there's no 'keyScene' property to find which scene is actually receiving the keys. So I can't reliably retrieve the true keyWindow, even if the windows themselves are clearly calling makeKeyAndVisible reliably because I see the semaphore in the window bar change colors.

That sounds about right. I'm able to reproduce this behavior on iPad with my command hierarchy. That, and the fact that disable states don't seem to update without changing the navigation stack pretty much breaks much of the keyboard shortcut behaviors I want to enable on iPad. I also didn't expect iPadOS to hide menu commands that are disabled, so discovery is a bit of a mess on iPad.

Even better, if I use something like Cmd-Right Arrow, iPad can't show the button that needs to be pressed, but Mac can. Awesome.

Menu Commands on iPad seem pretty borked right now. Especially since iOS seems to be acting like commands should be attached to views rather than scenes (similar to toolbars on iOS), but must be attached to the scene. Awesome. (/s)

If you got it working on Mac but it doesn't always fire on iPad, maybe I'm not getting it to work on macOS because I'm using Catalyst. I'll test my app on iPad to see how badly it works there.

I think that's the case. I just tried a multi-window scenario on macOS specifically again and the menu disable states were updating when switching the foreground window and doing nothing else. So Window A has a view up that enables the command, Window B doesn't, and the command is enabled when I bring A to the front, and disabled when I bring B to the front.
 

Andropov

Site Champ
Posts
593
Reaction score
725
Location
Spain
That sounds about right. I'm able to reproduce this behavior on iPad with my command hierarchy. That, and the fact that disable states don't seem to update without changing the navigation stack pretty much breaks much of the keyboard shortcut behaviors I want to enable on iPad. I also didn't expect iPadOS to hide menu commands that are disabled, so discovery is a bit of a mess on iPad.

Even better, if I use something like Cmd-Right Arrow, iPad can't show the button that needs to be pressed, but Mac can. Awesome.

Menu Commands on iPad seem pretty borked right now. Especially since iOS seems to be acting like commands should be attached to views rather than scenes (similar to toolbars on iOS), but must be attached to the scene. Awesome. (/s)
Yep, had the same problem with the .disabled buttons not changing on state change.

There's also no way of overriding the default macOS commands as far as I know. If you try .keyboardShortcut("I"), the shortcut is not even shown in the menu! In fact, I remember that when I first tried this, the entire CommandGroup disappeared from the menu if one of the buttons had a reserved keyboardShortcut. And I haven't found any list of what shortcuts are not allowed. Preview uses ⌘+I for toggling the inspector panel, so that's why I tried to use the same shortcut for my app (I try to be consistent with the system behaviour). Nope.

This is a good example of an API that, while nice, needs work to be usable. I bet they'll fix it this year.
 

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
There's also no way of overriding the default macOS commands as far as I know. If you try .keyboardShortcut("I"), the shortcut is not even shown in the menu! In fact, I remember that when I first tried this, the entire CommandGroup disappeared from the menu if one of the buttons had a reserved keyboardShortcut. And I haven't found any list of what shortcuts are not allowed. Preview uses ⌘+I for toggling the inspector panel, so that's why I tried to use the same shortcut for my app (I try to be consistent with the system behaviour). Nope.

I noticed that collisions are messy for sure. On the AppKit side collisions don’t get resolved in a deterministic way, and so things just break if two menu items declare the same keyboard shortcut. Fun.

That said, Cmd-I seems to work fine for me on both AppKit and UIKit. So not sure what collision you are running into. Seems like it would be the "Toggle Italics" command, but not sure how that would be available by default.
 

Andropov

Site Champ
Posts
593
Reaction score
725
Location
Spain
That said, Cmd-I seems to work fine for me on both AppKit and UIKit. So not sure what collision you are running into. Seems like it would be the "Toggle Italics" command, but not sure how that would be available by default.
Oh my god. I just tried it on my iPad an it shows the ⌘+I. If you've tried on AppKit and it works, then it's a Catalyst-only issue. Lol.
 

Nycturne

Elite Member
Posts
1,074
Reaction score
1,355
Oh my god. I just tried it on my iPad an it shows the ⌘+I. If you've tried on AppKit and it works, then it's a Catalyst-only issue. Lol.
Come to the dark side and tweak things on top of AppKit. We have cake and broken toolbars. :p

(I may have eaten the cake)
 

Andropov

Site Champ
Posts
593
Reaction score
725
Location
Spain
Come to the dark side and tweak things on top of AppKit. We have cake and broken toolbars. :p
Do you have tooltips? I want tooltips :(

I think it's too late for me to rewrite the app to use Catalyst now anyway. Specially so close to the WWDC.
 
Top Bottom
1 2