1

I'm not really sure how to properly title the question, so hopefully it is made clear here.

the use case is mostly hypothetical at the moment, but if I have an array of published objects where Child is itself an ObservableObject:

@Published var children: [Child]

then, if I update an individual Child's property which is also published, I'd like the publisher to fire.

(if we use value types, it triggers the entire array and functions easily, this is best for most solutions in my experience)

TestCase

import XCTest
import Combine

final class CombineTests: XCTestCase {
    final class RefChild: ObservableObject {
        @Published var name: String = ""
    }
    
    struct ValueChild {
        var name: String = ""
    }
    
    final class Parent: ObservableObject {
        @Published var refChildren: [RefChild] = []
        @Published var refNames: String = ""
        
        @Published var valueChildren: [ValueChild] = []
        @Published var valueNames: String = ""
        
        init() {
            $refChildren.map { $0.map(\.name).joined(separator: ".") } .assign(to: &$refNames)
            $valueChildren.map { $0.map(\.name).joined(separator: ".") } .assign(to: &$valueNames)
        }
    }
    
    func testChildPublish() {
        let parent = Parent()
        parent.refChildren = .init(repeating: .init(), count: 5)
        parent.valueChildren = .init(repeating: .init(), count: 5)
        XCTAssertEqual(parent.refNames, "....")
        XCTAssertEqual(parent.valueNames, "....")
        
        parent.refChildren[0].name = "changed"
        // FAILS
        XCTAssertEqual(parent.refNames, "changed....")
        
        parent.valueChildren[0].name = "changed"
        // PASSES
        XCTAssertEqual(parent.valueNames, "changed....")
    }
}
Logan
  • 52,262
  • 20
  • 99
  • 128

0 Answers0