也许您可以在我那黑暗而无知的道路上照亮一些光线? 我的目的地是一个SwiftUI应用,我可以在其中将组件注入视图中,并使系统在这些组件上运行一些逻辑。基础上的弱点使我重新开始滑坡。让我向您展示我的尝试!
protocol DataComponent: Component {
associatedtype DataType
var data: DataType { get set }
init()
init(data: DataType)
}
struct NameComponent: DataComponent { var data = "default" }
这是基本数据组件。我的实体组件系统使用的是EntitasKit。
enum Entities {
case source
...
}
protocol EntityServicing {
var context: Context { get }
func entity(_ entity: Entities) -> Entity
}
final class EntityService: EntityServicing {
let context = Context()
func entity(_ entity: Entities) -> Entity {
switch entity {
case .source:
guard let first = context.entities.first else {
return context.createEntity()
}
return first
...
}
}
}
这是应用程序范围的EntityService,它保存实体及其组件的上下文。它是使用Resolver注入的。
现在,这是SwiftUI中的视图。
struct ContentView: View {
@EntityState(.source, "Dale Cooper") var name: NameComponent
var body: some View {
Button(action: { name = NameComponent(data: "Dougie Jones") }) {
Text(name.data).padding()
}
}
}
EntityState就是它的发音;一个属性包装器,它捕获实体组件的状态并使它对SwiftUI可见。
@propertyWrapper
struct EntityState<C>: DynamicProperty where C: DataComponent {
@State private var state = C()
@Injected private var entityService: EntityServicing
private let entityID: Entities
private var entity: Entity { entityService.entity(entityID) }
init(_ id: Entities, _ data: C.DataType? = nil) {
self.entityID = id
if let data = data {
entity.set(C(data: data))
} else {
guard entity.has(C.cid) else {
entity.set(state)
return
}
}
_state = State(wrappedValue: entity.get()!)
}
public var wrappedValue: C {
get { entity.get()! }
nonmutating set { state = newValue }
}
mutating func update() {
entity.set(state)
}
}
SwiftUI注意到dynamic属性中的状态更改。单击该按钮可重新呈现视图并更新实体上的组件。
当我添加一个更改组件的系统时,这种基础开始崩溃。
class NameSystem: ReactiveSystem {
@Injected var entityService: EntityServicing
lazy var collector: Collector = Collector(
group: entityService.context.group(
Matcher(
all: [NameComponent.cid]
)
),
type: .added
)
let name = "Name System Added Here!"
func execute(entities: Set<Entity>) {
for e in entities {
if let data = e.get(NameComponent.self)?.data {
e.set(NameComponent(data: "Special Agent " + data))
}
}
}
}
问题是SwiftUI状态从不通知,但是我希望SwiftUI知道组件在系统更新时发生的更改。
我尝试了许多不同的方法:
如何从系统向状态分配组件,以便SwiftUI重新呈现?
我希望您发现这个有趣的问题要解决,并且它使您像我对解决方案一样好奇。至少我真的很兴奋。
祝大家有美好的一天!