gpt4 book ai didi

objective-c - forwardInvocation 到其他类而不是实例

转载 作者:搜寻专家 更新时间:2023-10-30 20:03:28 25 4
gpt4 key购买 nike

我有一个 facade我想将一些类方法调用转发给一些“静态”类的单例。

乍一看,forwardInvocation: 似乎是一个可能的解决方案,然而,NSInvocationinvokeWithTarget:setTarget: 只接受一个 id,即。 e.指向实例的指针,而不是类本身。我尝试将 [MyTargetClass class] 作为目标移交,但是当我调用 [Facade someForwardedMethod] 时,仍然出现“No known class method [...]”错误某处。当我调用 [[Facade sharedInstance] someForwardedMethod] 时,出现“No visible @interface [...] declares the selector [...]”错误。

当然我知道我还需要覆盖 respondsToSelector:methodSignatureForSelector:,所以我的代码如下所示:

- (BOOL)respondsToSelector:(SEL)aSelector {
if ([super respondsToSelector:aSelector]) {
return YES;
} else {
return [MyTargetClass respondsToSelector:aSelector];
}
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [MyTargetClass methodSignatureForSelector:selector];
}
return signature;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {

SEL aSelector = [anInvocation selector];

if ([MyTargetClass respondsToSelector: aSelector]) {
[anInvocation invokeWithTarget:[MyTargetClass class]];
} else {
[super forwardInvocation:anInvocation];
}
}

有没有办法让这项工作奏效,还是我必须选择另一种方法?


编辑:我已经尝试了 Rob Napier 在他的回答中提到的两种方式,这是我的发现:

我可以通过门面实例调用目标类中的类方法

[(id)[Facade sharedInstance] doSomethingClassyInTargetClass];

它比我希望的有点丑陋,但它确实有效。但是,当我处理外观类时,我无法在目标类中调用类方法。为了让编译器安静下来,我可以写

[(Class)[Facade class] doSomethingClassyInTargetClass];

但随后它会在运行时抛出“NSInvalidArgumentException”“[Facade doSomethingClassyInTargetClass]:无法识别的选择器发送到类 [...]”。显然,外观类的类方法在不考虑 forwardInvocation: 的情况下得到解析,但毕竟它前面有一个 -...

最佳答案

啊,当你添加“No visible @interface [...] declares the selector [...]”时,一切都清楚了。

考虑一种只有实例方法的更简单的形式。你实现了 -forwardInvocation:,然后你有这样的代码:

[obj doSomething];

现在,MyObject 实际上并没有在其 header 中声明 doSomething,即使它会响应它。所以编译器提示这可能行不通。解决方法是:

[(id)obj doSomething];

当您声明某些东西时 id,编译器会停止检查目标是否实际实现了选择器。但也有可能没有接口(interface)声明了doSomething。然后编译器再次怀疑它可能是一个拼写错误,并给你一个警告。我所说的“无接口(interface)”是指“没有编译器可以访问的接口(interface)”。编译器只能访问此编译单元中的接口(interface)(即 .m 文件及其包含的 header )。因此,您需要确保包含定义此选择器的 header 。

现在对于类,你不能使用id,但是你应该可以使用Class来实现同样的事情,比如:

[(Class)MyClass doSomethingClassy];

如果想看 RNObserverManager来自 iOS 的示例代码:PTL 第 4 章演示了类似的内容。

您绝对还应该查看 Ken Thomases 引用的 forwardTargetForSelector:


您不必将 sharedInstance 转换为 id。只需更改签名,因为您总是希望以这种方式使用它:

+ (id)sharedInstance;

关于objective-c - forwardInvocation 到其他类而不是实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10862984/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com