An experimental Swift framework for implementing component-based architecture in your applications. Componentized provides a simple yet powerful way to add, retrieve, and manage components on any object that conforms to the ComponentBased protocol.
- Type-safe component storage: Store and retrieve components using Swift's type system
- Qualified components: Support for multiple components of the same type using qualifiers
- Protocol-based design: Clean separation of concerns through the
ComponentBasedprotocol - Cross-platform support: Works on iOS 16+, macOS 14+, tvOS 16+, and visionOS 1+
- Zero dependencies: Lightweight framework with no external dependencies
To use Componentized, make your class conform to the ComponentBased protocol:
import Componentized
class GameObject: ComponentBased {
let componentStore = ComponentStore()
}Add components to your object:
let gameObject = GameObject()
// Add a simple component
gameObject.componentStore.addComponent(HealthComponent(health: 100))
// Add components with qualifiers to distinguish between similar types
gameObject.componentStore.addComponent("Primary Weapon", qualifier: "weapon1")
gameObject.componentStore.addComponent("Secondary Weapon", qualifier: "weapon2")Retrieve components using the convenient methods provided by the ComponentBased protocol:
// Get an optional component
if let health: HealthComponent = gameObject.component() {
print("Current health: \(health.value)")
}
// Get a component with explicit type
let health = gameObject.component(HealthComponent.self)
// Get a component with qualifier
let primaryWeapon: String? = gameObject.component(qualifier: "weapon1")
// Get a required component (crashes if not found)
let requiredHealth: HealthComponent = gameObject.requiredComponent()The ComponentStore class provides the core functionality:
let store = ComponentStore()
// Adding components
store.addComponent(MyComponent())
store.addComponent(AnotherComponent(), qualifier: "special")
// Retrieving components
let component: MyComponent? = store.component()
let qualifiedComponent: AnotherComponent? = store.component(qualifier: "special")
let requiredComponent: MyComponent = store.requiredComponent()Here's a complete example of a game entity using the component system:
import Componentized
// Define your components
struct HealthComponent {
var maxHealth: Int
var currentHealth: Int
}
struct PositionComponent {
var x: Float
var y: Float
}
// Create a componentized entity
class GameEntity: ComponentBased {
let componentStore = ComponentStore()
init() {
// Add initial components
componentStore.addComponent(HealthComponent(maxHealth: 100, currentHealth: 100))
componentStore.addComponent(PositionComponent(x: 0, y: 0))
}
func takeDamage(_ amount: Int) {
guard var health: HealthComponent = component() else { return }
health.currentHealth = max(0, health.currentHealth - amount)
componentStore.addComponent(health) // Update the component
}
func move(to x: Float, y: Float) {
var position: PositionComponent = requiredComponent()
position.x = x
position.y = y
componentStore.addComponent(position) // Update the component
}
}
// Usage
let entity = GameEntity()
entity.takeDamage(25)
entity.move(to: 10.0, y: 20.0)
if let health: HealthComponent = entity.component() {
print("Entity health: \(health.currentHealth)/\(health.maxHealth)")
}- iOS 16.0+
- macOS 14.0+
- tvOS 16.0+
- visionOS 1.0+
See the LICENSE file for licensing information.