我一直在搜索Apple的代表团和协议文档以找到答案,但是经过一天以上的时间,我决定放弃并让大家对此进行镜头。我有三个类:httpmanager,loginmanager和fetchmanager。您可能可以猜测这些课程做什么,但要明确...

  • httpmanager - 包装NsurlConnection,并为LoginManager和FetchManager提供了一个简单的接口,可以通过身份验证进行HTTP请求。
  • 登录器 / Fetchmanager - 基本上是同一类,但他们对HTTPManager的消息做出了不同的反应。

HTTPMANAGER希望代表实施HTTPManagerDelegate协议,LoginManager和FetchManager都这样做。登录名和提取曼格类还为我的应用程序委托提供了协议,以便数据可以一直返回到用户界面。

在我的申请代表中 init: 方法,我同时初始化登录名和获取管理器,并对两者进行以下警告:

warning: class 'MyAppDelegate' does not implement the 'HTTPManagerDelegate' protocol
warning: incompatible Objective-C types assigning 'struct HTTPManager *', expected 'struct LoginManager *'

初始化的两个类都不来自HTTPManager,但它们确实实现了HTTPManagerDelegate协议。产生上述警告的代码线是:

_loginMgr = [[LoginManager alloc] initWithDelegate:self];

所以到底是什么使登录器的 initWithDelegate: 方法返回 HTTPManager*?没有继承,我的返回类型是正确的,所以对我来说,这是一些我无法最好的伏都教。

这是我应用程序的外壳。可能有错别字和小小的矛盾,所以在假设句法问题之前问我:

// HTTPManager.h

@protocol HTTPManagerDelegate
...
@end

@interface HTTPManager : NSObject
{
    id <HTTPManagerDelegate> _delegate;
    ...
}

- (HTTPManager *) initWithDelegate:(id <HTTPManagerDelegate>)delegate;
...

@end

// LoginManager.h

@protocol LoginManagerDelegate
...
@end

@interface LoginManager : NSObject <HTTPManagerDelegate>
{
    id <LoginManagerDelegate> _delegate;
    ...
}

- (LoginManager *) initWithDelegate:(id <LoginManagerDelegate>)delegate;
...

@end

// MyAppDelegate.h

@interface MyAppDelegate : NSObject <NSApplicationDelegate, LoginManagerDelegate, FetchManagerDelegate>
{
    LoginManager *_loginMgr;
    ...
}

...

@end

// MyAppDelegate.m

...

- (MyAppDelegate *) init
{
    self = [super init];

    if (self)
    {
        // WARNING HAPPENS HERE
        _loginMgr = [[LoginManager alloc] initWithDelegate:self];
        ...
    }

    return self;
}

...

提前致谢。

有帮助吗?

解决方案

问题是您有两种具有相同方法签名的方法 -initWithDelegate: 但是在其参数和/或返回类型中有不同的类型。编译器不能很好地处理这种情况,在某些情况下,它也可能导致运行时错误(在您的情况下不是因为方法中的类型在尺寸上没有差异,它们都是指针)。

这样做(AFAIK)的原因是,运行时无法直接访问方法中使用的类型。它只是读取选择器(其中包含类型信息),并根据此选择器决定哪种方法。为了帮助运行时将方法参数打包到堆栈上,编译器在编译时间创建一个表,将选择器映射到参数并返回值类型。该表只有每个选择器一个条目。因此,如果存在两个具有相同选择器但参数或返回值不同类型的方法,则该系统可能会失败。

在您的情况下:

-init... 方法应始终返回 id 而不是特定类型。

这解决了不同返回类型的问题。另一个问题(不同的参数类型)更难解决。您可以从方法声明中省略协议规范(initWithDelegate:(id)delegate)或给出两种不同名称的方法:

- (id) initWithHttpMgrDelegate:(id <HTTPManagerDelegate>)delegate;
- (id) initWithLoginMgrDelegate:(id <LoginManagerDelegate>)delegate;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top