Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
commie kong
Mar 7, 2019

101 posted:

Am I missing something, or am I giving up on SwiftUI for another few years?

Hey, give this a try:

code:
struct Item {
    var name: String = ""
    var id: UUID = UUID()
}

struct ContentView: View {
    var items: [Item] = [Item(name: "test"), Item(name: "test2")]
    
    var body: some View {
        List {
            ForEach(items, id: \.id) { item in
                VStack(alignment: .leading) {
                    HStack {
                        Text(item.name)
                        Spacer()
                    }
                    .contentShape(Rectangle())
                    .onTapGesture {
                        print("Tapped")
                    }
                }
            }
            .onDelete {
                print("Deleting: \($0)")
            }
        }
    }
}
onTapGesture works correctly (doesn't interfere with onDelete) when applied to the Text view directly, but the hitbox is limited to the size of the text. So wrapping up each list row in a bunch of stacks and a spacer as above sorts that issue.

There may be better solutions, but this demonstrates a workaround at least

Adbot
ADBOT LOVES YOU

101
Oct 15, 2012


Vault Dweller

commie kong posted:

Hey, give this a try:

That seems to work, thanks. I did try something similar, but the Spacer turned out to be the secret sauce I was missing.

Also, just got an interview with a company whose apps are built 'entirely' in SwiftUI, so I guess I'd better keep tooling around with it.

I want to like it, but UIKit is like a warm blanket comparatively. Is this how people felt during the ObjC -> Swift transition?

Graniteman
Nov 16, 2002

101 posted:

I feel like I'm going crazy.

Every time I try SwiftUI, I hit some dumb but huge hurdle so quickly.

code:
List {
	
	ForEach(items, id: \.self) { item in
		
		Text(item)
	}
	.onDelete { indexSet in
		
		print("Delete")
	}
}
.onTapGesture {
	
	print("Tapped")
}
The tap gesture takes precedence over the onDelete so the onDelete almost never gets triggered or if it rarely does, it's at the same time as the tap gesture.
...

You have the .onTapGesture on the entire list, not on each list element.

101 posted:

That seems to work, thanks. I did try something similar, but the Spacer turned out to be the secret sauce I was missing.

Try using .contentShape(Rectangle()) instead of spacer. That viewmodifier is specifically to change the size / shape of the tap target for a view. I use it to solve this problem whenever it comes up.

Graniteman fucked around with this message at 14:55 on Sep 6, 2022

toiletbrush
May 17, 2010
How do I programmatically 'pop' a view in SwiftUI? I've got a List wrapped in a NavigationView, with each item having a navigation link to a 'detail' view that has a single editable text view. I want the detail view to pop back to the list view in the onCommit callback of the text field, but I can't figure out how to do it :(

Graniteman
Nov 16, 2002

toiletbrush posted:

How do I programmatically 'pop' a view in SwiftUI? I've got a List wrapped in a NavigationView, with each item having a navigation link to a 'detail' view that has a single editable text view. I want the detail view to pop back to the list view in the onCommit callback of the text field, but I can't figure out how to do it :(

That’s because apple didn’t build swiftui to let you do it. There are a number of ways to work around it, but you aren’t missing something obvious. Apparently in iOS 16 there is a new way to do navigation (NavigationView is deprecated!) which solves these problems and there is easy / good support for programmatic navigation. But prior to iOS 16 you have to roll your own navigation solution.

I don’t have a good solution to recommend to you, so I’ll just say you can google what’s out there.

toiletbrush
May 17, 2010
yeah ive found a few solutions but they seem weirdly complicated. am I going against some UI guidelines, or is it just another thing swiftui doesn't support for no obvious reason? Having an edit view dismiss itself when you've finished editing doesn't seem particularly controversial

Graniteman
Nov 16, 2002

toiletbrush posted:

yeah ive found a few solutions but they seem weirdly complicated. am I going against some UI guidelines, or is it just another thing swiftui doesn't support for no obvious reason? Having an edit view dismiss itself when you've finished editing doesn't seem particularly controversial

No, you are understanding correctly. There is no programmatic way to pop the navigation stack in swiftUI prior to iOS 16. After iOS 16 it’s totally reworked, presumably to solve the problems you are seeing.

You can easily have an edit view dismiss itself if you are using modal (sheet, fullScreenCover, etc). Binding to a @State isDisplayed bool in the calling UI is probably the standard swiftui approach, or using the @Environment dismiss() stuff if the modal supports it. What you can’t easily do is pop back multiple levels of a navigation view, or arbitrarily jump around with deep links in your navigation stack, unless you do the complicated stuff (or only support iOS 16).

Fate Accomplice
Nov 30, 2006




SwiftUI sounds like it sucks all around. It looks unreadable.

dizzywhip
Dec 23, 2005

It's subjective of course, but I think there's a lot to love with SwiftUI. When it works and properly supports all of your use cases, it's amazingly light and quick to build with, and the composability of its design is extremely powerful.

The main problem is just that it's still lacking in a lot of key areas, like navigation until iOS 16 as we just saw. All the power you feel is blunted by a sense of unease that just around the corner you're going to hit a brick wall and have to throw out everything you just built and replace it with UIKit or AppKit.

There are often workarounds for these kinds of problems, but a lot of times it'll end up being more complicated and messy than if you'd just gone with a kit from the beginning. The SwiftUI-Introspect package helps a lot to bridge the gap when there just isn't a SwiftUI way of doing something.

Overall I really like using it though, and I have a lot of hope for its future. It sucks having to wait an entire year between updates and probably another 3-5 years at least (plus X years to update your minimum deployment target) before enough gaps will be filled that it doesn't feel limited compared to the kits, but I think it's still worth using at this point for a lot of people.

Pulcinella
Feb 15, 2019
Probation
Can't post for 9 days!
I have had the same feeling of “Am I going crazy” around SwiftUI. My advice: stay off Twitter. Good advice in general, but also there are tons of people saying they’ve used SwiftUI in dozens of “production” apps without any problems, only to later reveal they are iPhone only (SwiftUI is pretty buggy on iPad, watch, and tvOS, really buggy on macOS, and insanely buggy on macOS <12.3 or 12.4) and basically two screens or is just wrapping UIKit and claiming the whole thing is SwiftUI.

I’m using it for collection view cells in iOS16, SwiftCharts, and widgets, but that’s about it. It’s so, so nice for how fast and easy simple things are, but beyond that you are likely to end up at dead end and need to re-implement in UKit/AppKit. Also the ease of use makes it too easy to kill performance. It’s easy to pass some published object into your views, only to find out that doing anything with it ramps CPU usage to 100% because every view is listening for any change and the app spends all its time diffing and calling the body property. You have to vend the absolute minimum amount of state to each view. The next thing you know you are managing all this state that the framework should be handling because the framework can’t be trusted.

I am feeling a bit curmudgeonly at the moment, so to be fair, I will reiterate that simple things are so, so fast and easy. If you have some largely static screen that doesn’t scroll, maybe with some buttons, e.g. something like a a sound board, you can knock those out so, so fast in SwiftUI. Stuff that would have taken me a few hours in UIKit can be done in 20 minutes in SwiftUI.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
It's really cool how Apple just decides that certain method names are forbidden on the app store with zero announcement or warning. Are we supposed to be scraping all of the private frameworks for selector names every time we name something to make sure we don't accidentally overlap?

Evis
Feb 28, 2007
Flying Spaghetti Monster

Plorkyeran posted:

It's really cool how Apple just decides that certain method names are forbidden on the app store with zero announcement or warning. Are we supposed to be scraping all of the private frameworks for selector names every time we name something to make sure we don't accidentally overlap?

It would be nice if they could just get Xcode (or some tool) to do that for you before you submit.

duck monster
Dec 15, 2004

Evis posted:

It would be nice if they could just get Xcode (or some tool) to do that for you before you submit.

People have been asking for access to apples static analyser since the beginning of the iphone sdk. It is, alas, not something apple has actually ever given us. Security reasons or something apparently.

Pulcinella
Feb 15, 2019
Probation
Can't post for 9 days!

duck monster posted:

People have been asking for access to apples static analyser since the beginning of the iphone sdk. It is, alas, not something apple has actually ever given us. Security reasons or something apparently.

Making it built into Xcode seems like the kind of thing that would benefit 99% of developers but the Facebooks of the world would just immediately begin to pull all-nighters to figure out all the limits and blind spots and how to exploit them; so we can’t have nice things.

dc3k
Feb 18, 2003

what.
who the hell is dylan

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?
a miserable pile of folk songs

also typesafe parentheses

also typesafe parentheses replaced by begin and end to entice people who hate lisp syntax… with Pascal syntax

eschaton fucked around with this message at 01:46 on Sep 22, 2022

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?
This primer shows the original language a bit, before it was made Pascal-flavored: It was basically Scheme plus CLOS with all the naming rationalized instead of kept traditional. (No more car and cdr etc.)

Good CS research was done to make the Pascal-style syntax happen while still providing a hygienic syntax-transformation macro system, but that instead of a focus on shipping ASAP and improving performance utterly destroyed what little market opportunity it would’ve had.

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?
Oh yeah, the Wayback Machine has a copy of an HTML conversion of an annotated version of the original Dylan: An Object Oriented Programming Language book.

The language it describes is still interesting today. Someone should implement it.

Small White Dragon
Nov 23, 2007

No relation.

Plorkyeran posted:

It's really cool how Apple just decides that certain method names are forbidden on the app store with zero announcement or warning. Are we supposed to be scraping all of the private frameworks for selector names every time we name something to make sure we don't accidentally overlap?

At least back in the day, if you really wanted to, you could dynamically construct those undocumented selectors in code and it would pass the test.

Not that I'm suggesting anyone do this.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
We're not calling any private things. We just have a method in our public API that happens to have the same name as a private thing in some game center framework.

SaTaMaS
Apr 18, 2003
The way SwiftUI handles focus seems bizarre to me. For every other UI library I've used, when you type in a text field and then click a button, the textfield loses focus before the action on the button is run, but on SwiftUI the textfield never loses focus so any handlers for that never get called if the button is pressed. Is there any way to rationalize this as anything other than a bug, and what is a clean way to force the lose focus handler on the text field to be called before the button action is run without creating dependencies between the components? I've tried putting sendAction/resignFirstResponder in the button handler, but that causes the lose focus handler to be called after the button action.

Small White Dragon
Nov 23, 2007

No relation.
I've been out of the iOS game for a while, and I have a Xamarin app that runs fine on iOS.

Are launch images still supported these days, or is that no longer supported?

Is there a way to handle the iPad status bar and make sure I can accept touches under that area?

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Small White Dragon posted:

I've been out of the iOS game for a while, and I have a Xamarin app that runs fine on iOS.

Are launch images still supported these days, or is that no longer supported?

Is there a way to handle the iPad status bar and make sure I can accept touches under that area?

A launch storyboard is required. I don't know if you can supplement it with launch images and if so for what resolutions.

You can hide the iPad status bar. When it's visible, there are buttons in it (back button in top left (after following a link to another app) and multitasking button in the middle), but I don't know what happens to touches in the foreground app. If you've been out long enough that you're not sure what the safe area is, that might be useful reading to help arrange views up there. https://useyourloaf.com/blog/safe-area-layout-guide/ looks like a decent summary.

uncle blog
Nov 18, 2012

I want to write a function that returns a boolean based on whether an item can be found in an array or not. The trouble is that the function giving me the array uses callbacks to interact with the resulting folder. I don't know how to get these two functions to play nice.

This is the existing thing:
code:
    func loadArrayOfThings( dataCallback: ((Response<[Thing]>) -> Void)? = nil) -> RequestToken? {
        return client.loadThings(dataCallback: { response in
            dataCallback?(response)
        })
    }
And I want to make something like this:
code:
func thingsIncludesThingWith(name: String) -> Bool {
	return things.contains(where: { $0.name == name })
}
And I just don't get how to make something like that work with the callback pattern. I tried something like this, but this fails as the return is called instantly before the callback can change it:
code:
    func thingsIncludesThingWith(name: String) -> Bool {
        var hasThing = false
        loadArrayOfThings(completion: { allTheThings in
            hasThing = allTheThings.contains(where: { $0.name == name })
        })
        return hasThing
    }

take boat
Jul 8, 2006
boat: TAKEN

uncle blog posted:

I want to write a function that returns a boolean based on whether an item can be found in an array or not. The trouble is that the function giving me the array uses callbacks to interact with the resulting folder. I don't know how to get these two functions to play nice.

the simplest/easiest thing is to change your function to take a completion callback and make this asynchronous for callers as well, so
code:
func thingsIncludesThingWith(name: String, completion: (Bool) -> Void)
(Recent Swift versions now have async/await to make this nicer.) it makes sense that if the underlying library is asynchronous, your function should also be

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Yeah. The most fundamental thing you’re missing is that the values are being passed to a callback so that they can be produced asynchronously, i.e. without tying up a thread just waiting until the values are available. There’s no way to make this available as a synchronous return value without blocking the current thread until the callback is called, which is possible but generally a bad idea. You need to think about how to handle this asynchrony in your design, either by making your own result asynchronous or by introducing some kind of staging where e.g. you kick off the query and then respond “I don’t have an answer yet” until the information comes back.

SaTaMaS
Apr 18, 2003
How do you make a deep copy of a Set in Swift? I'm trying to transfer a Set containing a Core Data relationship from one thread to another, and I'm getting a Core Data error which I'm pretty sure is because of the bridged NSSet reference hiding in the Set type.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

SaTaMaS posted:

How do you make a deep copy of a Set in Swift? I'm trying to transfer a Set containing a Core Data relationship from one thread to another, and I'm getting a Core Data error which I'm pretty sure is because of the bridged NSSet reference hiding in the Set type.

You don't need a deep copy, you need a shallow copy :)

Probably the best way overall would be to take a set of managed object IDs from the source thread and reify them back into managed objects on the destination thread:
Swift code:
// source thread
let ids = coolObject.relatedObjects.map(\.objectID)
// destination thread
let objects = ids.map { context.object(with: $0) }
However, if you really want the objects themselves in a non-Core Data set, try
Swift code:
var copy: Set<RelatedObject> = []
copy.formUnion(coolObject.relatedObjects)

101
Oct 15, 2012


Vault Dweller

101 posted:

I feel like I'm going crazy.

Every time I try SwiftUI, I hit some dumb but huge hurdle so quickly.

...

Am I missing something, or am I giving up on SwiftUI for another few years?

Welp, I got an offer I couldn't refuse from a company whose app is built entirely in SwiftUI. Guess I'm gonna have to get to grips with it.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

101 posted:

Welp, I got an offer I couldn't refuse from a company whose app is built entirely in SwiftUI. Guess I'm gonna have to get to grips with it.

Congrats!

Also lol

Small White Dragon
Nov 23, 2007

No relation.
Is Xcode 14.1 not out yet? I wasn't sure if upgrading to iOS 16.1/iPad OS 16.1 would cause issues with Xcode 14.0.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Small White Dragon posted:

Is Xcode 14.1 not out yet? I wasn't sure if upgrading to iOS 16.1/iPad OS 16.1 would cause issues with Xcode 14.0.

I saw the 14.1 release candidate was out end of last week (by which I mean it was available in whatever feed the Xcodes app polls, idk about App Store).

Heads up though it has a Swift Concurrency bug that wrecks the AsyncSequence backport, if you have any iOS devices <15 you'll wanna keep Xcode 14.0.1 around still.

former glory
Jul 11, 2011

101 posted:

Welp, I got an offer I couldn't refuse from a company whose app is built entirely in SwiftUI. Guess I'm gonna have to get to grips with it.

I'm such a declarative UI convert after learning SwiftUI that this sounds like a nice scenario, congrats and good luck with the change. In my experience so far, once you get the UI to do what you need in 100% swift, it's rock solid and has far fewer unexpected cases. But it can be a bit of a fight at first.

Doing some work with Flutter now and it's following a lot of the same patterns in UI construction, but it just feels a lot messier in how these widgets end up as massive chains of constructors rather than the clean ViewBuilder way of doing the same thing in Swift. There a big advantage in SwiftUI's approach in just being able to break the View statements up from the dev's perspective in parsing it all vs. the View(child: AnotherView(children: [child1(), child2(child: fart(color: blue, child: ...))])). The IDE's auto-formatter is doing a lot of heavy lifting just visually making a tree out of the gnarly web of calls.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
There's a second Xcode 14.1 RC out so I guess there was a problem with the first.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Plorkyeran posted:

There's a second Xcode 14.1 RC out so I guess there was a problem with the first.

https://developer.apple.com/documentation/xcode-release-notes/xcode-14_1-release-notes mentions some concurrency issues. Nothing about AsyncStream though, wonder if that's fixed too. I'll try it out!

Small White Dragon
Nov 23, 2007

No relation.
Apparently Cameron v Apple is paying out settlements although I haven't seen anything yet.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

pokeyman posted:

https://developer.apple.com/documentation/xcode-release-notes/xcode-14_1-release-notes mentions some concurrency issues. Nothing about AsyncStream though, wonder if that's fixed too. I'll try it out!

This was indeed fixed. 14.1RC2 is a winner!

Pulcinella
Feb 15, 2019
Probation
Can't post for 9 days!

Small White Dragon posted:

Apparently Cameron v Apple is paying out settlements although I haven't seen anything yet.

Settlement amounts are much, much larger because way fewer people signed on than could have. E.g. The minimum payout went from ~$250 to ~$1000.

SaTaMaS
Apr 18, 2003
Is anyone using ViewInspector to unit test SwiftUI? I'm about to start using it since it seems like the only game in town, but I'm hesitant because
1. It requires inserting boilerplate code into Views in order to test @State vars
2. Apple could come out with a way to unit test SwiftUI at any time
3. The owner is Russian and hasn't posted in a month, what happens if he gets conscripted?

Adbot
ADBOT LOVES YOU

uncle blog
Nov 18, 2012

In our UIKit app, there's a class that returns a UIView based on a switch clause. It has no knowledge of the viewController that will receive the view.
I created a new SwiftUI view and added a switch case returning that new view.

This is the basic implementation:
code:
case .rental:
	let rentalVC = UIHostingController(rootView: RentalView())
        return rentalVC.view
My coworker thinks this implementation is bad since view lifecycle management is handled differently in both UIKit and SwiftUI, and without adding the hosting VC to the parent VC (which I have no access to at this location), we might end up experiencing weird layout or performance issues. So I wonder if there's a better way to pass a SwiftUI view as a UIView (without having access to the VC)?


This is on iOS14.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply