- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个 facade我想将一些类方法调用转发给一些“静态”类的单例。
乍一看,forwardInvocation:
似乎是一个可能的解决方案,然而,NSInvocation
的 invokeWithTarget:
和 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/
我经常这样做: CoolViewController *coolViewController = [[CoolViewController alloc] init]; [self.navigation
我无法让 forwardInvocation 工作。出于某种原因,Objective-C 运行时完全忽略了我的 forwardInvocation: 方法并抛出无法识别的选择器异常。 我的测试代码如下
我有一个 facade我想将一些类方法调用转发给一些“静态”类的单例。 乍一看,forwardInvocation: 似乎是一个可能的解决方案,然而,NSInvocation 的 invokeWith
我正在努力通过外观类转发类方法。 为了澄清,我重写了以下所有方法: -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector -(
我有一个问题。 我有方法 - (void)forwardInvocation:(NSInvocation *)anInvocation { SEL sel = anInvocation.selecto
对 objective-c 很陌生,但我遇到了一种似乎很常见的情况:我希望 ClassA 要求 ClassB 在只有 ClassB 知道的对象上执行一个方法(并且还使用了一个方法是A 级不知道)。 我
为了学习,我正在尝试更改在对象上调用的方法。 这是我的代码。 #import @interface A : NSObject -(void) say: (NSString*) s; -(NSMeth
仅查看 Objective-C 运行时库,当消息发送到不响应它的对象时,运行时系统会为接收方提供另一个机会来处理该消息。因此,接收方的 forward:: 方法(如果已实现)将被调用。然而,看着NSO
我正在获取 [_WebSafeForwarder forwardInvocation:] 和关于 crashlytics 的崩溃报告。无法在我的代码中重现相同的情况。我在每个 -(void)deall
我正在写 OpenStruct 的克隆在 Objective-C 中,使用 forwardInvocation: .但是,编译器显然不知道编译时的转发。用 ARC 编译给了我很多警告。 该代码是开源的
我有一个正在转发接收消息的对象。它不使用 forwardInvocation 实现将它们转发给其他对象。但是,由于程序的组织方式,methodSignatureForSelector 在某些时候并不总
我有一个正在转发接收消息的对象。它不使用 forwardInvocation 实现将它们转发给其他对象。但是,由于程序的组织方式,methodSignatureForSelector 在某些时候并不总
这是我的代码的一部分: - (void)viewDidLoad { [super viewDidLoad]; CGRect frame = [[UIScreen mainScreen]
以下代码实现了一个 NSProxy 子类,它将方法转发给一个 NSNumber 实例。 然而,在调用 [nsproxy floatValue] 时,我在 GCC 4.2 下得到 0.0。 在 LLVM
这是我用来测试行为的独立 test.m 文件。 编译:clang test.m -o test.app -fobjc-arc -ObjC -framework Foundation。确保已安装 Xco
我是一名优秀的程序员,十分优秀!