13

As of today's release of iOS 14.0 my iOS code, which depends heavily on GeometryReader for layout, is no longer working well. I.e, layout has been kind of randomized.

In the Xcode debugger I have compared the same code running on iOS 13.6 vs iOS 14.0 and see that the problem is that the GeometryProxy structure is not being initialized in iOS 14.0.

In the example code below the variable g, a GeometryProxy, has valid width and height values in iOS 13 but is all zero's in iOS 14. (This is just one of the simpler uses I make of GeometryProxy values -- I would appreciate if nobody points out the obvious fact that this snippet could be accomplished much more easily in another way.)

Is this a change to the GeometryReader or a bug? Anyone have a workaround? Did I make a huge mistake depending on GeometryReader for dynamic layout?

struct TextView: View {
  @EnvironmentObject var data: RecorderData
  let m = MusicalNote()

  var body: some View {
      GeometryReader { g in
          Stack(alignment: .leading) {
              Text(self.data.curNote.getString())
                 .font(.system(size: g.size.height / 2.4))
                 .padding(.bottom)
              Text(self.data.fdata.fingerings[self.data.curRecorder.id] ![self.data.curNote.seq] ![self.data.curFingType] ![self.data.currentFingeringChoice].comment)
                 .font(.headline)
        }
      Spacer()
    }
  }
}
5
  • Any different behavior on system update worth submitting feedback, and the sooner is the better. Commented Sep 17, 2020 at 16:26
  • Would you prepare minimal reproducible example? Commented Sep 17, 2020 at 17:30
  • I tried doing a very simple example to reproduce this and found that with just one view or one view and one subview the GeometryProxy was being properly populated. I am going through my app code to see if I can find something that's different (aside from size and complexity) and if I can find that will add it to the example. Commented Sep 17, 2020 at 18:22
  • Is it possible that the GeometryProxy values are set in a separate thread? I ask this because it does seem that though the values are zero the first time through the view's code, if there is a data update which requires repainting the view, the values are set -- but sometimes not until the 2nd or 3rd time through, and it seems to vary. At any rate I am not able to reproduce this in a very simple example. It would be good to know if anyone else is experiencing the issue. Commented Sep 17, 2020 at 19:50
  • Same issue with me, anyone can help what happening? Commented Sep 20, 2020 at 12:13

2 Answers 2

8

It's definitely changed - this post sums it up: https://swiftui-lab.com/geometryreader-bug/

GeometryReader now lays out its content different to how it used to. It used to centre it horizontally and vertically in the parent but now it aligns it to the top-left.

My app looks awful - what's frustrating is it's not clear if this is new behaviour and is as-designed, or whether it's a bug and will be fixed. I'm trying to go through my app and manually apply offsets but the dynamic nature of layouts using GeometryReader means it is not always easy.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for this link. But I think there are two things going on here. The link you reference describes one problem -- the change in alignment. The problem I described is related to when the GeometryProxy values are filled in. I was seeing zeros in the proxy size parameters and have concluded that this was because I was calculating my dynamic sizings in .onAppear(). In iOS 13 the proxy size parameters were already set when .onAppear was called, but not in iOS 14. I have resolved my problem by moving my sizing calculations to the main body of the view instead of .onAppear().
I share your frustration... what a bug.
@lp1756 I was seeing a similar issue where the proxy values were 0 when I was trying to use them in .onAppear(). Although in your example it doesn't look like you were using .onAppear()?
@bze12 you are right. In my example, when run in the debugger, the proxy values are zero with iOS 14 but good with iOS13 -- .onAppear() is not a factor in the example. All I know for sure is that in my app, when I moved the use of the proxy values from .onAppear to the body of the view, the app started correctly calculating the dynamic layout. I am still puzzled as to the exact nature of this bug/change -- but my app is now working (until they change something else in iOS 15!!)
2

Editing my previous answer as its now obviously bad advice

From https://developer.apple.com/documentation/xcode-release-notes/xcode-12-release-notes

Rebuilding against the iOS 14, macOS 11, watchOS 7, and tvOS 14 SDKs changes uses of GeometryReader to reliably top-leading align the views inside the GeometryReader. This was the previous behavior, except when it wasn’t possible to detect a single static view inside the GeometryReader. (59722992) (FB7597816)

Which says, to me at least, that the previous behaviour was buggy by their standards - despite it matching the conventions for other layout containers like VStack. And that this behaviour is the new normal.

1 Comment

Yeah: "... to reliably break everything you've recently written..." would be more accurate!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.