取消分配后删除Observer

时间:2013-09-21 22:50:02

标签: ios objective-c event-handling observer-pattern

我有以下两个班级:

此事件:



    @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特定解决方案。

那么,这可能吗?

非常感谢!

0 个答案:

没有答案