SwiftUI ScrollViewが更新されませんか?


10

ゴール

に表示するデータを取得する scrollView

期待される結果

scrollviewに表示されるデータ

実結果

空白のビュー

オルタナティブ

を使用しますがList、柔軟性がありません(セパレーターを削除できない、複数の列を持つことはできません)

コード

struct Object: Identifiable {
    var id: String
}

struct Test: View {
    @State var array = [Object]()

    var body: some View {
//        return VStack { // uncomment this to see that it works perfectly fine
        return ScrollView(.vertical) {
            ForEach(array) { o in
                Text(o.id)
            }
        }
        .onAppear(perform: {
            self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
        })
    }
}

私はこれをXcode 11.1、iOS 13.1、Swift 5でテストし、期待どおりの結果を得ています(スクロールビューは中央ではなく上部にあります)。
sfung3

また、キーワードは必要ありませんreturn
。– sfung3

興味深いことに、私はXcode 11.2、iOS 13.2、Swift 5を使用しています
youjin

ええ、私はprint以前に声明をしました、それゆえにreturn
youjin '13

Xcode 11.2に更新し、これを再現できるかどうかを確認します。しばらく時間がかかるかもしれませんが、私の調査結果を更新します。
sfung3

回答:


10

この問題を回避するためのそれほどハックではない方法は、配列が空かどうかを確認するIFステートメントでScrollViewを囲むことです。

if !self.array.isEmpty{
     ScrollView(.vertical) {
          ForEach(array) { o in
               Text(o.id)
          }
     }
}

この回避策は完璧です。ありがとうございます。
Hendrik

1

期待される動作が発生するXcode 11.1が、発生しないXcode 11.2.1

私は、追加frameの修飾子をScrollView作るどのScrollView現れます

struct Object: Identifiable {
    var id: String
}

struct ContentView: View {
    @State var array = [Object]()

    var body: some View {
        ScrollView(.vertical) {
            ForEach(array) { o in
                Text(o.id)
            }
        }
        .frame(height: 40)
        .onAppear(perform: {
            self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
        })
    }
}

残念ながら、シミュレータのiOS 13.2では動作しません
youjin

1

空の配列ではなく、ある値で状態が初期化された場合、期待どおりに機能することがわかりました(Xcode 11.2)。この場合、更新は正しく機能し、初期状態は影響しません。

struct TestScrollViewOnAppear: View {
    @State var array = [Object(id: "1")]

    var body: some View {
        ScrollView(.vertical) {
            ForEach(array) { o in
                Text(o.id)
            }
        }
        .onAppear(perform: {
            self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
        })
    }
}

これは単純なケースで機能します。私のケースではにネットワークコールがonAppearあるため、ダミーデータを使用してscrollViewを初期化すると問題が発生する可能性があります
youjin

正しいが、この状況はコードで論理的に処理できます。最初のオブジェクトは、簡単に検出できるスタブであり、「ロード」などの条件付きで何かを表示できるためです。私にとってはこれで十分です...共有する価値があります。
Asperi

1

私が見つけた一つのハックの回避策は、「目に見えない」を追加することであるRectangleと、scrollView内widthのデータの幅よりも値以上に設定scrollView

struct Object: Identifiable {
    var id: String
}

struct ContentView: View {
    @State var array = [Object]()

    var body: some View {
        GeometryReader { geometry in
            ScrollView(.vertical) {
                Rectangle()
                    .frame(width: geometry.size.width, height: 0.01)
                ForEach(array) { o in
                    Text(o.id)
                }
            }
        }
        .onAppear(perform: {
            self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
        })
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.