News for hackers. Stuff that matters.
Re:Static Types in SwiftUI by Razengan on Tuesday November 05, 2019 @06:03PM (#21457753)
I tend to run into these when weaving a lot of SwiftUI + non-SwiftUI code together.

A simple example: [0]. There are workarounds for this specific issue, but trying to do complex stuff sometimes surfaces inscrutable limitations that I can't quite figure out. And with no documentation relevant to a particular case, no Google hits, not even on Apple's forums, and the uncertainty of error messages, I'm not even sure if I'm doing something wrong or it just can't/shouldn't be done. I have to try random things until it works...until it doesn't.

I'm currently experimenting with a SwiftUI layer for a game engine [1], and running into weird undocumented differences between macOS and iOS (like view backgrounds clipping at stack container edges on macOS but not on iOS) that I can't be sure if they're bugs or what. Still, I love SwiftUI.

Also see EmptyView [2]

[0] https://gist.github.com/ShinryakuTako/5a7b32bbf4f4c3874439c2...

[1] https://github.com/InvadingOctopus/octopuskit

[2] https://forums.swift.org/t/how-do-views-like-emptyview-confo...

Re:Static Types in SwiftUI by lilyball on Tuesday November 05, 2019 @06:41PM (#21458123)
I assume your goal with [0] is to be able to say `ViewContainer()` and have it wrap an `EmptyView`? You can do that like the following:

  class ViewContainer<ViewType: View> {
      var view: ViewType
      init(view: ViewType) {
          self.view = view
      }
  }
  
  extension ViewContainer where ViewType == EmptyView {
      convenience init() {
          self.init(view: EmptyView())
      }
  }
With this code, writing `ViewContainer()` will produce a `ViewContainer<EmptyView>`. Writing `ViewContainer<Text>()` will fail with an error (as expected).

Note that since this is statically-typed, the following will fail:

  let container = ViewContainer()
  container.view = Text("wat")
If you want to be able to do that, you'd have to write something like

  let container = ViewContainer(view: AnyView(EmptyView()))
  container.view = AnyView(Text("wat"))
Re:Static Types in SwiftUI by Razengan on Tuesday November 05, 2019 @06:50PM (#21458214)
I love the extension idea, noting that for later. :)

But I do need to be able to change the view during runtime, so I settled on just type-erasing to AnyView for now.

Re:Static Types in SwiftUI by lilyball on Tuesday November 05, 2019 @07:57PM (#21458690)
If you have a set number of possible view types you could in theory have it hold onto an enum of the different types.
Re:Static Types in SwiftUI by DelightOne on Tuesday November 05, 2019 @06:15PM (#21457874)
I think the issue is that a variable's type can't be set by the outside (via the template parameter ViewType) and by the inside (to be of type EmptyView) at the same time. You have to decide.

Your workaround is to use the AnyView type I guess. Or a conditional with either EmptyView or the template type (displayed).

What would be the name of the feature that allows you to use a default template type if no argument is given to figure out the type to use?

Re:Static Types in SwiftUI by Razengan on Tuesday November 05, 2019 @06:20PM (#21457925)
> Your workaround is to use the AnyView type I guess.

Yes, I made the init generic instead of the type, and made the property an AnyView, but I've read that AnyView may decrease performance (probably because of reasons discussed in this post's article.)

Re:Static Types in SwiftUI by DelightOne on Tuesday November 05, 2019 @06:33PM (#21458052)
True. You could work around it by conditionally extending your ViewContainer to have a default constructor (init()), if the type is EmptyView. Then you can write

    var viewContainer2 = ViewContainer<EmptyView>()
But that's probably not what you want is it. Default generic arguments aren't implemented yet, see (https://stackoverflow.com/questions/42015081/can-i-assign-a-...). It would have possibly removed the <EmptyView> aspect. So you always have to give a type to ViewContainer, if you provide no way for the compiler to infer it.
Re:Static Types in SwiftUI by Razengan on Tuesday November 05, 2019 @06:37PM (#21458093)
> var viewContainer2 = ViewContainer<EmptyView>()

Yes, that would be a workaround for myself, but for a game engine's API, it'd be ugly to require users to write that every time. :)

And there are cases where they might not even know the type.

Re:Static Types in SwiftUI by DelightOne on Tuesday November 05, 2019 @06:46PM (#21458174)
It seems the compiler might be smarter than I thought he is (see a poster above), if so I learnt something new. :)

And it seems I didn't understand your problem, you wanting a variable that can change it's type instead of just some syntactic sugar, hmm.