我有以下两个课程:
事件调度程序:
@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
事件订阅者:
#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
关于一个大问题:我如何减轻使用该系统的程序员在释放期间必须取消订阅事件的负担?当多个类使用这个系统时,程序员必须记住在释放期间取消订阅(如果不是更早的时间),否则可能会发生非常糟糕/奇怪/意外的事情(我更喜欢编译时检查,或者一个大的、明显的,可调试的崩溃,但更是如此)。理想情况下,我想重构这个系统(或做任何事情),以便当一个对象被释放时,EventDispatcher 可以优雅地处理它。
一种快速的解决方法是让对象直接分配 EventSubscribers,然后在 EventSubscriber 构造函数中,它自己订阅 EventDispatcher(但这显然很糟糕,也许让 EventDispatcher 的东西静态?呃,现在我们变得更糟了)。
旁注:
我没有使用 ARC,但是,这并不重要(至少我认为没有关系,如果有基于 ARC 的解决方案,我想听听它们)。
我确实计划在 EventDispatcher 中添加一个方法,以便能够通过订阅者删除 EventSubscribers(所以现在订阅时,对象必须传递“自我”)。我还计划让枚举的 EVENT_TYPE 使用字符串,但这完全是一个不同的话题。
我还计划将我的很多代码(包括这些类)翻译成 C++。所以我很欣赏一个概念性的解决方案,而不是 Objective-C 特定的解决方案。
那么,这可能吗?
非常感谢!