OGWAspect Class Reference
Inherits from | NSObject |
Conforms to | OGWNotifierDelegate |
Declared in | OGWAspect.h |
Overview
Aspects are code plugins for entities or the world. Each subclass of OGWAspect provides custom code and/or data that can be used while the aspect is added to an entity.
Subclassing Notes
Aspects are normally added automatically to each entity when the entity is assigned to a category. The OGWEntityCategory class contains a list of aspect classes to instantiate and add to each entity.
Aspects should therefore be developed to remain on an entity throughout its lifetime, rather than adding/removing entities as needed. This would not only be inefficient for performance but also changes the order in which aspects are updated, which is often important.
To temporarily disable an aspect, you can use the enabled property to program the aspect to stop updating or performing any other work (as needed) when it is not enabled. That way you can temporarily remove functionality without having to remove or replace an aspect.
Aspects should always subclass from OGWAspect. If you find the need to subclass from a more concrete aspect subclass, then while that is legal it may indicate a flaw in your class design. The indiciation being a lack of generalization or perhaps the aspect is doing too much already and should be broken down into multiple decoupled aspects, with the intended subclass now becoming one of the fragment aspects.
Conventions
World aspects should follow the OGWWorldAspect naming convention, whereas entity aspects simply omit the reference to entity: OGWAspect.
Aspects should not use custom initializers but use safe default values and expose all modifiable settings as properties. All aspects can be created through the aspectWithWorld: and aspectWithEntity: initializers.
In subclasses override the following methods to perform initialization and set default values, setup with and caching of other aspects, and performing cleanup work:
-(void) aspectDidInitialize
-(void) ownerDidAddAspect:(OGWAspect)addedAspect
-(void) ownerWillRemoveAspect:(OGWAspect)removingAspect
Refering to other Aspects
When one aspect often needs another aspect, it can cache the reference locally but only in a __weak
ivar/property to
avoid potential memory leaks (retain cycles).
Alternatively one aspect can provide a delegate to receive events, either by adding a delegate property or by using the notifier which should be used when there may be more than one delegate interested in the aspect’s events.
In delegation it is customary to provide the sending aspect as the first parameter in every delegate method. That way the sender is clear and the receiver can access additional data from the sender as needed. Example aspect delegate methods:
-(void) aspect:(OGWContactAspect)aspect contactWithEntity:(OGWEntity)contact category:(const OGWEntityCategory)category;
-(BOOL) aspect:(OGWStateAspect)aspect shouldChangeState:(GWState)newState currentState:(GWState)currentState reason:(GWReason)reason;
-(void) aspect:(OGWWorldGravityAspect*)aspect gravityDidChange:(GWVector)gravity;
Warning: If aspect A directly references aspect B while aspect B directly references aspect A you have a code smell. Typically one aspect provides the work needed by another aspect - two closely interacting aspects in a back-and-forth manner indicate that they are tightly coupled, and should either be merged into one or one abstracted to work without the other (tip: delegation).
Tasks
Creating an Aspect
Owner
Delegation
-
notifier
property
Enabled
-
enabled
property
Methods for Subclasses
Properties
enabled
The enabled state can be used by aspects as they see fit, it has no inherent function. Typically an aspect will use the enabled flag to stop update processing while it is not enabled.
@property BOOL enabled
Return Value
Whether the aspect is enabled.
Discussion
The enabled flag plays an important role because aspects are not supposed to be added/removed as needed, but instead most aspects are added the moment an entity is created and remain on the entity until the entity deallocates. The enabled flag thus can be used to control temporarily disabled aspects.
Declared In
OGWAspect.h
entity
The entity owning the aspect.
@property (weak, readonly) OGWEntity *entity
Return Value
The entity owning the aspect.
See Also
Declared In
OGWAspect.h
notifier
Some aspects use the notifier to send delegate messages to multiple delegate. Refer to the specific aspect’s documentation to learn whether it uses the multi-delegation notifier.
@property (readonly) OGWNotifier *notifier
Return Value
The notifier, or nil if the aspect does not support multi-delegation.
See Also
Declared In
OGWAspect.h
Class Methods
aspectWithEntity:
Creates a designated entity aspect.
+ (id)aspectWithEntity:(OGWEntity *)entity
Parameters
- entity
The entity to which the aspect will be added.
Return Value
A new aspect.
See Also
Declared In
OGWAspect.h
Instance Methods
aspectDidInitialize
Sent when the OGWAspect class ran its init method. You’re not supposed to override the usual init methods in an aspect class, so instead place any initialization code and setting default values to this method.
- (void)aspectDidInitialize
Discussion
Warning: This message is not supposed to be sent by user code. It is sent from OGWAspect.
Declared In
OGWAspect.h
createNotifierWithProtocol:
This will create a OGWNotifier object and initialize it with the given protocol. Aspect subclasses use this to allow sending delegate messages to multiple delegates via the OGWNotifier object. The protocol is used to ensure (to some extent) type safety of the delegates.
- (void)createNotifierWithProtocol:(Protocol *)protocol
Parameters
- protocol
The protocol that delegates have to implement.
Discussion
Warning: This message is not supposed to be sent from another object to an aspect.
See Also
Declared In
OGWAspect.h
ownerDidAddAspect:
Sent when the aspect was added to its owner, which depending on the aspects intended use can either be the world or an entity.
- (void)ownerDidAddAspect:(OGWAspect *)addedAspect
Parameters
- addedAspect
The aspect that was added.
Discussion
Typically aspects test either for addedAspect == self
to perform further initialization when being added to an owner,
and/or test for ‘[addedAspect isMemberOfClass:[OGWSomeOtherAspect class]]` to find a specific aspect that may be added
only after this aspect has been added.
Warning: This message is not supposed to be sent by user code. It is sent from OGWAspect.
Declared In
OGWAspect.h
ownerWillRemoveAspect:
Sent before the aspect is removed from its owner, which depending on the aspects intended use can either be the world or an entity.
- (void)ownerWillRemoveAspect:(OGWAspect *)removingAspect
Parameters
- removingAspect
The aspect that will be removed.
Discussion
Typically aspects test either for addedAspect == self
or ‘[addedAspect isMemberOfClass:[OGWSomeOtherAspect class]]`
to perform cleanup work for themselves or when another aspect they depend on is removed.
Warning: This message is not supposed to be sent by user code. It is sent from OGWAspect.
Declared In
OGWAspect.h