【问题标题】:How do i fix duplicate declaration of method with out breaking code如何在不破坏代码的情况下修复方法的重复声明
【发布时间】:2016-02-21 14:14:10
【问题描述】:

我正在尝试将 Google 登录 SDK 包含到我的 AppDelegate.m 文件中,但它会引发此错误。

好像我只能定义一个方法的实例。

// Facebook SDK
- (void)applicationDidBecomeActive:(UIApplication *)application {
  [FBSDKAppEvents activateApp];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                        openURL:url
                                              sourceApplication:sourceApplication
                                                     annotation:annotation];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

  return [RNGoogleSignin application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
}

@end

【问题讨论】:

  • 那么其他 - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 包含什么?
  • @hariszaman。我认为它包含打开 GoogleSignin 的逻辑。开发工具包。我只是想在不了解目标 c 的情况下为 react-native 实现登录

标签: objective-c


【解决方案1】:

我想答案可能很简单:

- (BOOL)application:(UIApplication *)application 
            openURL:(NSURL *)url 
  sourceApplication:(NSString *)sourceApplication 
         annotation:(id)annotation 
{
    if([[FBSDKApplicationDelegate sharedInstance] application:application
                                                      openURL:url
                                            sourceApplication:sourceApplication
                                                   annotation:annotation])
    {
        return YES;
    }

    return [RNGoogleSignin application:application 
                               openURL:url
                     sourceApplication:sourceApplication 
                            annotation:annotation];
}

如果您添加更多,则在任何代理处理 openURL 时返回 YES。顺序无关紧要。此外,此方法已被弃用(请改用-application:openURL:options:),因此如果您希望您的应用在未来的更改中继续存在,则需要避免使用-application:openURL:sourceApplication:annotation:

UPD:如果您“现在就想要”,请使用我的解决方案,gaussblurinc 的解决方案也有优点,所以如果您想要长期使用某些东西 - 肯定会从中获得一些东西。

【讨论】:

  • 它可以通过处理这些方法的“服务”实例/类来改进。
  • 另外,责任链可以解决这个问题
  • 这可以在很多方面进行改进,我只是在这里提供最简单的答案。您可以随意添加所有这些详细信息的答案。
  • 检测你的计划怎么样?喜欢这里stackoverflow.com/questions/20848913/…
  • @hariszaman 你可以通过“服务”来完成,这个简单的解决方案只会增加复杂性和问题的数量
【解决方案2】:
@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

毕竟

您可以将所有 AppDelegate 方法委托给外部类。

您的问题是“广泛使用 appDelegate 方法”。

似乎没有人愿意清理应用程序中的应用程序委托,因为“它可以正常工作”。我只是向您展示(是好是坏?不知道)责任链模式和简单委托的示例。

请记住,您可以将大部分 AppDelegate 方法委托给其他对象/类,例如,您可以提供智能的“PushNotificationsRouter”来处理所有与推送通知相关的方法。

【讨论】:

  • 是的,这很好,但仍有待改进。我建议将所有具体实现包装到一个适配器中,这样它可能比这更安全。此外,看起来您的解决方案违反了改变原则的单一责任或单一原因,并且就目前的情况而言,从长远来看,每个“服务”在整个画面中所做的事情之间的关系可能难以理解(即你检查responsToSelector,这意味着你承担未来增加的责任)。
  • 但总的来说,是的,您的解决方案是一种可行的方法,我更喜欢您认为更优雅的东西。有我的+。
  • 另外,请注意,人们只是复制/粘贴您的代码然后遵守他们会得到愚蠢的错误。这就是这个世界的滚动方式。无论如何,你解决了那些架构问题,这很好,但问题是那些需要相应问题的人,那些不需要的人(我认为,在这种情况下)可能不会欣赏你的努力。所以我支持你的意图,只是不要对别人不礼貌。
  • @MANIAK_dobrii,请对您的评论投赞成票 :) 我相信美丽的新世界,如果您阅读了它,那么只有 beta 和 alpha 可以编码;)
猜你喜欢
  • 1970-01-01
  • 2021-04-08
  • 2020-06-24
  • 2019-10-08
  • 2021-12-02
  • 2016-09-01
  • 1970-01-01
  • 2014-08-24
  • 1970-01-01
相关资源
最近更新 更多