Why isn't onPreferenceChange being called if it's inside a ScrollView in SwiftUI?

前端 未结 5 2064
逝去的感伤
逝去的感伤 2021-01-02 02:57

I\'ve been seeing some strange behavior for preference keys with ScrollView. If I put the onPreferenceChange inside the ScrollView it won\'t be cal

5条回答
  •  爱一瞬间的悲伤
    2021-01-02 03:23

    I had been trying to figure out this issue for a long time and have found how to deal with it although the way I used was just the one of workarounds.

    Use onAppear to ScrollView with a flag to make its children show up.

    ...
    @State var isShowingContent = false
    ...
    
    ScrollView {
        if isShowingContent {
            ContentView()
        }
    }
    .onAppear {
         self.isShowingContent = true
    }
    

    Or,

    Use List instead of it.
    It has the scroll feature and you can customize it with its own functionality and UITableView appearance in terms of UI. the most important is that it works as we expected.

    [If you have time to read more]
    Let me say my thought about that issue.

    I have confirmed that onPreferenceChange isn't called at the bootstrap time of a view which is put inside a ScrollView. I'm not sure if it is right behavior or not. But, I assume that it's wrong because ScrollView have to be capable to contain any views even if some of those use PreferenceKey to pass any data among views inside it. If it's right behavior, it would be quite easy of us to get in trouble when we try to create our custom views.

    Let's get into more detail.
    I suppose that ScrollView would work slightly different from the other container views such as List, (H/V)Stack when it comes to setup its child view at the bootstrap time. In other words, ScrollView would try to draw(or lay out) children in its own way. Unfortunately, that way would affect the children's layout mechanism working incorrectly as what we've been seeing. We could guess what happened with the following message on debug view.

    TestHPreferenceKey tried to update multiple times per frame.

    It might be an evidence to tell us that the update of children has occurred while ScrollView is doing something for its setup. At that moment, it could be guessed that the update to PreferenceKey has been ignored.

    That's why I tried to put the placing child views off to onAppear.

    I hope that will be useful for someone who's struggling with various issue on SwiftUI.

提交回复
热议问题