我有以下两个班级:
此事件:
@interface EventDispatcher()
-(id)initEventDispatcher;
-(NSMutableArray*)getSubscriptionsToEvent:(EVENT_TYPE)eventType;
-(NSNumber*)getKeyToEvent:(EVENT_TYPE)eventType;
@end
@implementation EventDispatcher
static EventDispatcher* eventDispatcher;
// Singleton.
+(EventDispatcher*)instance
{
if (eventDispatcher == nil)
{
eventDispatcher = [[EventDispatcher alloc] initEventDispatcher];
}
return eventDispatcher;
}
-(id)initEventDispatcher
{
self = [super init];
if (self)
{
eventSubscriptions = [[NSMutableDictionary alloc] init];
}
return self;
}
// Let anyone subscribe to an event. Return the EventSubscriber so they can dispatch events if needed, and to be able to unsubscribe.
-(EventSubscriber*)subscribe:(EVENT_TYPE)eventType :(void(^)(id package))operateEvent
{
// Create the object.
EventSubscriber* eventSubscriber = [[EventSubscriber alloc] initEventSubscriber:eventType :operateEvent];
// Now get the list it belongs to (we sort subscriptions in a dictionary so that when we dispatch an event, it's fast (we don't need to iterate through all EventSubscribers to find who subscribe to an event).
NSMutableArray* subscriptionsToThisEvent = [self getSubscriptionsToEvent:eventType];
if(subscriptionsToThisEvent == nil)
{
// If the list is nil, no one has subscribed to it yet, so make that list and add it to the dictionary.
subscriptionsToThisEvent = [[NSMutableArray alloc] init];
NSNumber* key = [self getKeyToEvent:eventType];
[eventSubscriptions setObject:subscriptionsToThisEvent forKey:key];
[subscriptionsToThisEvent release];
}
// Add the EventSubscriber to the subscription list.
[subscriptionsToThisEvent addObject:eventSubscriber];
[eventSubscriber release];
return eventSubscriber;
}
-(void)unsubscribe:(EventSubscriber*)eventSubscriber
{
// Get the list it belongs to, and remove it from that list.
EVENT_TYPE eventType = [eventSubscriber getEventType];
NSMutableArray* subscriptionsToThisEvent = [self getSubscriptionsToEvent:eventType];
if (subscriptionsToThisEvent != nil)
{
[subscriptionsToThisEvent removeObject:eventSubscriber];
}
}
-(void)dispatch:(EVENT_TYPE)eventType :(id)package
{
NSMutableArray* subscriptionsToThisEvent = [self getSubscriptionsToEvent:eventType];
// If no one has subscribed to this event, it could be nil, so do nothing.
if (subscriptionsToThisEvent != nil)
{
// Otherwise, let them all know that the event was dispatched!
for (EventSubscriber* eventSubscriber in subscriptionsToThisEvent)
[eventSubscriber dispatch:package];
}
}
// Helper methods to get stuff (lists, keys) from event types.
-(NSMutableArray*)getSubscriptionsToEvent:(EVENT_TYPE)eventType
{
NSNumber* key = [self getKeyToEvent:eventType];
NSMutableArray* subscriptionsToThisEvent = [eventSubscriptions objectForKey:key];
return subscriptionsToThisEvent;
}
-(NSNumber*)getKeyToEvent:(EVENT_TYPE)eventType
{
return [NSNumber numberWithInt:eventType];
}
-(void)dealloc
{
[eventSubscriptions release];
[super dealloc];
}
@end
EventSubscriber:
#import "EventSubscriber.h"
@implementation EventSubscriber
-(id)initEventSubscriber:(EVENT_TYPE)newEventType :(void(^)(id package))newOperateEvent
{
self = [super init];
if (self)
{
operateEvent = [newOperateEvent copy];
eventType = newEventType;
}
return self;
}
-(void)dispatch:(id)package
{
operateEvent(package);
}
-(EVENT_TYPE)getEventType
{
return eventType;
}
-(void)dealloc
{
[operateEvent release];
[super dealloc];
}
@end
在一个大问题上:如何解除使用此系统的程序员在解除分配期间不必取消订阅事件?当多个类使用这个系统时,程序员必须记住在解除分配期间取消订阅(如果不是更早的时间),或者真的可能发生错误/奇怪/意外的事情(我更喜欢编译时检查,或者是大的,明显的,debuggable崩溃,但更多 - 所以前者)。理想情况下,我想重构这个系统(或做任何事情),这样当一个对象被释放时,EventDispatcher会优雅地处理它。
一个快速解决方法是让对象直接分配EventSubscribers,然后在EventSubscriber构造函数中,它将自己订阅到EventDispatcher(但这显然很糟糕,可能使EventDispatcher的东西变得静止?现在我们变得更糟)。
附注:
我没有使用ARC,但是,这并不重要(至少我认为它没有,如果有基于ARC的解决方案,我想听听它们。)
我计划在EventDispatcher中添加一个方法,以便能够通过订阅的人删除EventSubscribers(所以现在订阅时,对象必须通过'self')。我还计划使用枚举的EVENT_TYPE使用字符串,但这完全是另一个主题。
我还计划将很多代码(包括这些类)翻译成C ++。所以我很欣赏概念解决方案而不是Objective-C特定解决方案。
那么,这可能吗?
非常感谢!