1

I got this inside LazyVstack:

                            ForEach(memes, id: \.memeid){
                                meme in

                                if(!user.hiddenUsersString.contains(String(meme.userid) + ",")){
                                    
                                    GeometryReader{ proxy in
                                        
                                        MemeView(memeid: meme.memeid,
                                            picUrl: Functions.getMediaUrl(media: meme.pic, serverScaling: serverScaling,
                                            whichMedia: "memes"),
                                            profilImgUrl: finalImgUrl(theUrl: Functions.getProfileImg(userid: meme.userid, serverScaling: serverScaling, imgTag: user.userid == meme.userid ? user.profilePicTag : nil), memeOwner: meme.userid),
                                            memeWidth: memeWidth,
                                            memeHeight: Functions.getMemeHeight(memeWidth: memeWidth, fileName: meme.pic, memeSize: meme.size),
                                            position: proxy.frame(in: .global).origin.y,
                                            meme: meme,
                                            memes: self.$memes)
                                
                                    }
                                }
                            }

In the body of MemeView I got:

        VStack{

            HStack{
                AsyncImage(url: URL(string: profilImgUrl)) { phase in
                    switch phase {
                    case .empty:
                        ProgressView()
                            .scaleEffect(x: 1.5, y: 1.5, anchor: .center)
                            .aspectRatio(contentMode: .fit)
                            .frame(maxWidth: 34)
                    case .success(let image):
                        image.resizable()
                             .aspectRatio(contentMode: .fit)
                             .frame(maxWidth: 34)
                             .cornerRadius(50)
                    case .failure:
                        Image(systemName: "person.circle.fill")
                            .resizable()
                            .aspectRatio(contentMode: .fit).frame(height: 34)
                            .cornerRadius(50)
                            .foregroundColor(Color.gray)
                    @unknown default:
                        Image(systemName: "person.circle.fill")
                            .resizable()
                            .aspectRatio(contentMode: .fit).frame(height: 34)
                            .cornerRadius(50)
                            .foregroundColor(Color.gray)
                    }
                }
                
                Text(meme.nickname)
            }
            .frame(height: 30)
            
            ZStack{
                if(meme.pic.contains(".mp4")){
                    VideoPlayer(player: player)
                        .frame(width: memeWidth,
                               height: memeHeight,
                               alignment: .center)
                }else{
                    AsyncImage(url: URL(string: picUrl)) { phase in
                        switch phase {
                        case .empty:
                            ProgressView()
                                .scaleEffect(x: 1.5, y: 1.5, anchor: .center)
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 34)
                        case .success(let image):
                            image.resizable()
                                 .aspectRatio(contentMode: .fit)
                                 .frame(width: memeWidth, height: memeHeight)
                                 .cornerRadius(50)
                        case .failure:
                            Image(systemName: "person.circle.fill")
                                .resizable()
                                .aspectRatio(contentMode: .fit).frame(height: 34)
                                .cornerRadius(50)
                                .foregroundColor(Color.gray)
                        @unknown default:
                            Image(systemName: "person.circle.fill")
                                .resizable()
                                .aspectRatio(contentMode: .fit).frame(height: 34)
                                .cornerRadius(50)
                                .foregroundColor(Color.gray)
                        }
                    }
                }
            }
            .frame(width: memeWidth, height: 500)
        }
        .task {

            if(meme.pic.contains(".mp4")){
                player = AVPlayer(url: URL(string: picUrl)!)
            }
        }

Everything is squeezed together! VStack completely ignores the height of the children views.

Why is that and how to fix this?

I'm new to iOS / SwiftUI and must say that I absolutely loathe it. I'm shocked that apple think it's ok to release such a bugged and limited pile garbage into the world!

  • I would take out the VSTack in the `MemeView` itself, you already functionally have it available with the usage of the `LazyVStack`. You might consider refactoring the GeometryReader out as well, I can't see how it's useful in your example. – xTwisteDx Dec 09 '22 at 19:16
  • I need the item position to be updated by GeometryReader to calculate when a video can be automatically played. I removed the VStack but everything is still squeezed and extremely and randomly messed up – Eduard Unruh Dec 09 '22 at 19:24
  • I just removed the GemetryReader and it looks fine now, but what alternative can I use to track item position to the top of the screen? – Eduard Unruh Dec 09 '22 at 19:27
  • Should I delete this question and ask for a solution with geometryreader? – Eduard Unruh Dec 09 '22 at 19:30
  • I believe you can look at the view hierarchy and get the details about it's positioning on the screen from the properties of that view. Let me think about this for just a moment. – xTwisteDx Dec 09 '22 at 19:33
  • The thing about the Geometry Reader is that it changes the way that the views lay themselves out, which is why it changed when you removed it. It's a funky thing to deal with. If you're wanting to enable the auto-play when it becomes visible use the `.onAppear {}` and `.onDisappear {}` modifiers. They can be used on anything that uses the `View` protocol, which in your case it does. Also it should work wonderfully with the LazyVStack. – xTwisteDx Dec 09 '22 at 19:34
  • Have a look here for a bit more clarity. https://stackoverflow.com/questions/60595900/how-to-check-if-a-view-is-displayed-on-the-screen-swift-5-and-swiftui – xTwisteDx Dec 09 '22 at 19:36

1 Answers1

1

First thing you should do is remove the VStack located in your MemeView, when you consider your overall structure you have something like this, which is not what I believe you're expecting.

LazyVStack {
    VStack {
        //Your MemeViewContent
    }
}

As you can see, you have a LazyVStack and then another VStack inside of it, when your outer LazyVStack manages your expected view just fine.

The next step is to refactor out the GeometryReader OR, moving it higher in the view stack. Currently you have it ForEach individual view, so it's going to cause the views contained inside of it, to be resized unexpectedly. Effectively, you've got a bunch of really small Frames inside of your ForEach loop, which then you're attempting to use as if it was taking up the entire screen, effectively chopping it into very small parts, eg squished views. A better solution would be to make use of the .onAppear{} or .onDisappear{} modifiers, or get the view's properties and calculate it that way. Ultimately, I would always recommend avoiding GemometryReader except in special circumstances. If you're hard-stuck needing to have to use the GeometryReader have a look here for a usage of it, where you'd bring it down to a more child view position and make use of the proxy. https://stackoverflow.com/a/73038067/12417531

onAppear/onDisappear Resources: How to check if a view is displayed on the screen? (Swift 5 and SwiftUI)

Geometry Reader Resources: https://swiftwithmajid.com/2020/11/04/how-to-use-geometryreader-without-breaking-swiftui-layout/

xTwisteDx
  • 2,152
  • 1
  • 9
  • 25
  • Thanks! I can't test it out with .onAppear{} yet since I'm facing another dumb problem but your answer solved the messed up ordering. – Eduard Unruh Dec 09 '22 at 19:54