Skip to content

Instantly share code, notes, and snippets.

@jmibanez
Last active October 15, 2025 16:35
Show Gist options
  • Select an option

  • Save jmibanez/ea2d938503ee43b5cd242dd43fe215e2 to your computer and use it in GitHub Desktop.

Select an option

Save jmibanez/ea2d938503ee43b5cd242dd43fe215e2 to your computer and use it in GitHub Desktop.
SwiftUI/AttributeGraph bug?
import SwiftUI
import SwiftData
@Model
final class Container {
var box: BoxInstance?
var shape: ShapeInstance?
init(box: BoxInstance?, shape: ShapeInstance?) {
self.box = box
self.shape = shape
}
}
@Model
final class BoxInstance {
var name: String
var fixedShape: ShapeInstance?
var shapeType: String?
var hasFixedShape: Bool {
return shapeType == nil && fixedShape != nil
}
@Relationship(deleteRule: .nullify, inverse: \Container.box)
var currentContainer: Container? = nil
#Index<BoxInstance>([\.shapeType])
init(name: String, fixedShape: ShapeInstance?, shapeType: String?) {
self.name = name
self.fixedShape = fixedShape
self.shapeType = shapeType
}
}
@Model
final class ShapeInstance {
var name: String
var shapeType: String?
@Relationship(deleteRule: .nullify, inverse: \Container.shape)
var currentContainer: Container? = nil
#Index<ShapeInstance>([\.shapeType])
init(name: String, shapeType: String?) {
self.name = name
self.shapeType = shapeType
}
}
struct ContainerView: View {
private var boxes: [BoxInstance]
private var shapes: [ShapeInstance]
@State var container: Container
init(container: Container, boxes: [BoxInstance], shapes: [ShapeInstance]) {
self.container = container
self.boxes = boxes.filter { box in
box.currentContainer == nil || box.currentContainer == container
}
if let shapeType = container.box?.shapeType {
self.shapes = shapes.filter { shape in
shapeType == shape.shapeType
}
} else {
self.shapes = shapes.filter { shape in shape.shapeType == nil }
}
}
var body: some View {
// Defensive: reset shape if not in current valid options
if !(container.box?.hasFixedShape ?? false) {
if container.shape != nil && !shapes.contains(where: { $0 === container.shape }) {
container.shape = nil
}
}
return GroupBox {
ControlGroup {
Picker(selection: $container.box) {
Text("NA").tag(nil as BoxInstance?)
ForEach(boxes, id: \.self) { box in
Text(box.name).tag(box as BoxInstance?)
}
} label: {
Label("", systemImage: "archivebox")
}
.pickerStyle(.navigationLink)
if !(container.box?.hasFixedShape ?? false) {
Divider()
Picker(selection: $container.shape) {
Text("NA").tag(nil as ShapeInstance?)
ForEach(shapes, id: \.self) { shape in
Text(shape.name).tag(shape as ShapeInstance?)
}
} label: {
Label("", systemImage: "dot.squareshape")
}
.pickerStyle(.navigationLink)
}
} label: {
Text("Box")
}
}
}
}
struct ContentView: View {
private var containers: [Container]
private var boxes: [BoxInstance]
private var shapes: [ShapeInstance]
init() {
let fixedShape = ShapeInstance(name: "Fixed", shapeType: nil)
let otherShape1 = ShapeInstance(name: "Round", shapeType: "Round")
let otherShape2 = ShapeInstance(name: "Circular", shapeType: "Round")
let box1 = BoxInstance(name: "Box A", fixedShape: nil, shapeType: "Round")
let box2 = BoxInstance(name: "Box B", fixedShape: fixedShape, shapeType: nil)
let container1 = Container(box: box1, shape: otherShape1)
self.containers = [container1]
self.boxes = [box1, box2]
self.shapes = [otherShape1, otherShape2, fixedShape]
}
var body: some View {
NavigationStack {
List {
ForEach(containers, id: \.self) { c in
ContainerView(container: c, boxes: boxes, shapes: shapes)
}
}
}
}
}
@main
struct SwiftUIMinimalPickerBugSampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment