@interface Services : NSObject<UIApplicationDelegate> // or ApplicationDelegateServices?
@property (strong, nonatomic, readonly) NSArray <id<UIApplicationDelegate>> *services;
@end
@interface Services()
@property (strong, nonatomic, readwrite) NSArray <id<UIApplicationDelegate>> *services;
@end
@class RNGoogleSignin;
@class FBSDKApplicationDelegate;
@implementation Services
- (void)setup {
// put all items inside here
//
id<UIApplicationDelegate> googleApplicationDelegate = (<UIApplicationDelegate>)[RNGoogleSignin class];
id<UIApplicationDelegate> facebookApplicationDelegate = (<UIApplicationDelegate>)[FBSDKApplicationDelegate sharedInstance];
self.services = @[facebookApplicationDelegate, googleApplicationDelegate];
}
// services - create chain of responsibility for openURL scheme
// they only need to adopt to protocol canOpenURL and openURL
// each service is <UIApplicationDelegate>
- (NSArray <id<UIApplicationDelegate>>*) chainForSelector:(SEL)selector {
return [self.services filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id<UIApplicationDelegate> _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject respondsToSelector:selector];
}]];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
// find all that responds to selector
// filteredArrayUsingPredicate
NSArray *chain = [self chainForSelector:_cmd];
// or put your custom logic here, because all items in delegate are good enough to perform selector
for (id<UIApplicationDelegate> delegate in chain) {
if([delegate application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation]) {
return YES;
}
}
return NO;
}
@end
@interface AppDelegate<UIApplicationDelegate>
@property (nonatomic, weak) id<UIApplicationDelegate> services;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
// check that services responds to delegate method
// if ([services respondsToSelector:...])
if ([self.services respondsToSelector:_cmd]) {
return [self.services application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation];
}
return NO/YES; // your choice
}
@end
After all
You can delegate all AppDelegate methods to external classes.
Your trouble was 'extensive usage of appDelegate methods'.
It seems that nobody wants to cleanup app delegate in apps because 'it just works'. I just show you ( bad or good? don't know ) an example of chain of responsibility pattern and simple delegation.
Remember, you can delegate most of your AppDelegate methods to other objects/classes, for example, you can provide smart 'PushNotificationsRouter' that will handle all push notification-related methods.