Apostolos Apostolidis
Apostolos Apostolidis

Reputation: 189

Dynamically set and un-set event listeners in Objective C

I have used obj c delegates a couple of times and know their basic use. But I have the following problem:

I use the Dropbox SDK for iOS and use their builtin delegate method for DeltaEntriesLoaded. But I use it from two different positions in my code. From the first position I want to do my "normal stuff" but from the second position I want as soon as the delta entries are loaded to access an array filled by this DeltaEntries method.

So, I have a class which calls LoadDelta but, depending on when it is calling it, it needs to have a different behavior right after the DeltaEntries are loaded. How do I solve that?

Upvotes: 0

Views: 329

Answers (1)

Josh Gafni
Josh Gafni

Reputation: 2881

Is the problem that only one object can be declared as the delegate on which deltaEntriesLoaded will be called, but you need it to be called in more than one place?

It might be a good idea to create an intermediate object that interacts with the DropboxSDK. For example, you might have a DropboxManager singleton object that serves as the delegate. The DropboxManager will have an array of DropboxManagerListeners - the objects in your code that need to be notified when the delta entries are loaded. The DropboxManager will then loop through the listeners and call deltaEntriesLoaded on each listener, to notify them.

The pseudocode would be:

DropboxManager.h

@protocol DropboxManagerListener <NSObject>

- (void)deltaEntriesLoaded:(NSArray *)deltaEntries;

@end

@interface DropboxManager : NSObject

+ (DropboxManager *)sharedManager

- (void)addListener:(id<DropboxManagerListener *>) listener;

@end

DropboxManager.m

@interface DropboxManager () <DropboxDelegate>

@property (copy, nonatomic) NSArray<DeltaManagerListener *> *listeners;

@end

@implementation

+ (DropboxManager *)sharedManager {
    static DropboxManager *sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedManager = [[self alloc] init];
        //set sharedManager as the DropboxSDKDelegate here
    });
    return sharedManager;
}

- (void)addListener:(id<DropboxManagerListener *>)listener {
    self.listeners = //code to do self.listeners + listener
}

- (void)deltaEntriesLoaded:(NSArray *)deltaEntries { //Delegate method from Dropbox SDK 
    for id<DeltaManagerListener *> listener in self.listeners {
         [listener deltaEntriesLoaded:deltaEntries];
    }
}

@end

So when you need an object to be notified of the deltaEntriesLoaded, just make sure they adhere to the DropboxManagerListener protocol and add themselves as a listener by calling [[DropboxManager sharedManager] addListener:yourObject];

It's nice to separate out any code dealing with a third party into one single class and have other code interact with the intermediate class. This way, if you ever end up needing to switch to a different third party, you might not have to change as much code.

Upvotes: 1

Related Questions