ずっと5月

3日坊主してます

SwiftUIのForEachでViewの繰り返し表示が上手く出来なかったときのメモ

上手く行かないやつ
init時点でstrListに存在するものに関しては表示されるが、途中で追加されたものが描画されなかった

class StateValue: ObservableObject {
    @Published var strList: [Moji]

    struct Moji {
        var title: String
        var location: CGPoint
        var size: CGFloat
        var angle: Angle
        var color: Color
        
        public init( title: String,
                     location: CGPoint = .init(x: 120, y: 20),
                     size: CGFloat = 20,
                     angle: Angle = .init(degrees: 0.0),
                     color: Color = .black
        ) {
            self.title = title
            self.location = location
            self.size = size
            self.angle = angle
            self.color = color
        }
    }
ForEach(0..<list.count) { index in
                        let item = list[index]
                        Text(item.title)
                            .foregroundColor(item.color)
                            .position(item.location)
                            .rotationEffect(item.angle)
                            .gesture(
                                DragGesture()
                                        .onChanged { value in
                                            state.strList[index].location = value.location
                                            state.isDragging = true
                                        }
                                        .onEnded { _ in
                                            state.isDragging = false
                                        }
                            )
                    }

上手く行かないのはForeachの仕様らしい
最終的に繰り返したい構造体をIdentifiableに準拠させて、Foreachの書き方を変えて動作させた

class StateValue: ObservableObject {
    @Published var strList: [Moji]

    struct Moji: Identifiable {  // Identifiableに準拠させる
        var id = UUID()
        var title: String
        var location: CGPoint
        var size: CGFloat
        var angle: Angle
        var color: Color
        
        public init( title: String,
                     location: CGPoint = .init(x: 120, y: 20),
                     size: CGFloat = 20,
                     angle: Angle = .init(degrees: 0.0),
                     color: Color = .black
        ) {
            self.title = title
            self.location = location
            self.size = size
            self.angle = angle
            self.color = color
        }
    }
ForEach(Array(list.enumerated()), id: \.offset) { index, item in 
                        Text(item.title)
                            .foregroundColor(item.color)
                            .position(item.location)
                            .rotationEffect(item.angle)
                            .gesture(
                                DragGesture()
                                        .onChanged { value in
                                            state.strList[index].location = value.location
                                            state.isDragging = true
                                        }
                                        .onEnded { _ in
                                            state.isDragging = false
                                        }
                            )
                    }

developer.apple.com

ja.stackoverflow.com