siteline/swiftui-introspect

Setting scrollview delegate on List breaks cells update

Closed this issue · 2 comments

Description

Looks like it doesn't want to update cells correctly after setting the scroll view delegate through Introspect.

import SwiftUI
import Combine
import SwiftUIIntrospect

struct CellModel {
    let id: String
    let title: AnyPublisher<String, Never>
    
    init(id: String, title: String) {
        self.id = id
        self.title = CurrentValueSubject(title).eraseToAnyPublisher()
    }
}

struct Cell: View {
    private let model: CellModel
    
    @State private var title = "unchanged"
    
    init(_ model: CellModel) {
        self.model = model
    }
    
    var body: some View {
        Text(title)
            .onReceive(model.title) { value in
                title = value
            }
    }
}

struct ContentViewModel {
    let cells: [CellModel]
    init() {
        var tmp: [CellModel] = []
        for index in 0...10 {
            tmp.append(.init(
                id: UUID().uuidString,
                title: String(index)
            ))
        }
        cells = tmp
    }
}

struct ContentView: View {
    private let model: ContentViewModel
    
    private let delegate = ScrollViewDelegate()
    
    init(_ model: ContentViewModel) {
        self.model = model
    }
    
    var body: some View {
        List {
            ForEach(model.cells, id: \.id) { model in
                Cell(model)
            }
        }
        .introspect(.scrollView, on: .iOS(.v15, .v16, .v17)) { scrollView in
            scrollView.delegate = delegate
        }
    }
}

private class ScrollViewDelegate: NSObject, UIScrollViewDelegate {}

Checklist

Expected behavior

Screenshot 2024-07-15 at 17 13 28

Actual behavior

Screenshot 2024-07-15 at 17 13 48

Steps to reproduce

  1. Create simple SwiftUI project
  2. Replace the code of ContentView with the above code
  3. Run and see the actual behaviour (screenshot above)
  4. Comment the introspect modifier and see the expected behaviour (screenshot above)

Version information

No response

Destination operating system

Simulator iPhone 15 Pro - 17.2

Xcode version information

15.1

Swift Compiler version information

No response

@davdroman Thank you, it makes sense. But it's still not clear to me how the delegate can prevent the cells from firing their .onReceive, .onAppear, .onChange and .task methods when they are already drawn on the screen.

Perhaps someone knows how to set up the delegate to solve the problem of updating cells?