- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
对 objective-c 很陌生,但我遇到了一种似乎很常见的情况:我希望 ClassA 要求 ClassB 在只有 ClassB 知道的对象上执行一个方法(并且还使用了一个方法是A 级不知道)。
我找到了两种方法:performSelector: 和 forwardInvocation: - 但我想了解更多并加深对每种方法的理解。我在苹果开发者文档中找到了这条注释:
The aSelector argument [in performSelector:] should identify a method that takes no arguments. For methods that return anything other than an object, use NSInvocation.
..这是否意味着以 - (id)methodName 开头的方法将使用 performSelector:,而说 - (int)nonObjectMethodName 会使用 forwardInvocation:?
返回 (void) 的方法又如何呢?或返回非 id 对象的方法,例如(NSString)?
最佳答案
没有。 -forwardInvocation:
用作消息转发机制的一部分。不要担心消息转发,因为它实际上只被代理对象使用,而且你永远不需要使用它并且知道你正在使用它的可能性很大。
-performSelector:
假定消息的返回类型是 id
或兼容的,因此如果它用于发送返回类型不同的消息(例如比指针更宽,例如 32 位系统上的 long long
,或者通过不同的寄存器/地址返回,例如 float
或大型 struct
.)
如果你想间接发送这样的消息,你可以创建 NSInvocation
类的实例,然后发送它 -invoke
.然后将返回值存储在调用对象中,并可以通过它访问。 -forwardInvocation:
在这种情况下您永远不会使用。
一般来说,如果您发现自己在使用 -performSelector:
,您可能正在处理反模式。在这种情况下,您正试图发送一条 ClassA
并不知道的消息。替代解决方案是公开这些私有(private)方法。
如果您同时拥有 ClassA
和 ClassB
,您可以为 ClassB
创建一个包含您想要的私有(private)方法的“私有(private)” header 采用。如果其他人(例如 Apple)拥有 ClassB
,您正在处理未记录的 API,并且可能需要寻找另一种方法,因为 Apple 将拒绝使用此类 API 的应用。
要创建私有(private) header ,请进入 Xcode 并创建一个新的 header 文件。将其命名为“ClassB+Internal.h”或“ClassB+PrivateMethodsForMeOnly.h”。将其视为您的项目的私有(private)文件——除非他们与 ClassB
是对等的(相同的子项目或库或组件),否则没有人可以使用它。在这个新标题中,添加以下内容:
#import "ClassB.h" // so we get the original class definition
@interface ClassB (PrivateMethodsForMeOnly)
- (double)someMethod;
- (const struct low_level_c_type_t)otherMethod:(int)i;
// etc. etc. etc.
@end
并且在 ClassA.m
中(不是 ClassA.h
除非你想将这些方法公开给所有使用 ClassA< 的人
!) 在您的包含部分中添加以下行:
#import "ClassB+PrivateMethodsForMeOnly.h"
ClassA
此后将可以访问新类别中的那些方法。
关于Objective-C:performSelector:与 forwardInvocation:,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11379525/
这个问题在这里已经有了答案: performSelector may cause a leak because its selector is unknown (19 个回答) 关闭 9 年前。
使用此语句会立即调用选择器,而不是从现在开始 6 秒。 this.PerformSelector(myStartWaitForSoundSelector, null, 6.0f); 有谁知道如何让它延
如果我用这个开始做某事: > [self performSelector:@selector(runThis:) > withObject:thisObject > afterDelay
虽然它在模拟器上似乎不会造成问题,但在设备上使用 performSelectorInBackground 会导致内存泄漏。或者至少 Instruments 是这么表示的。查看代码我没有任何线索可能是什
我有一个包含多个部分的 UITableView。每个部分包含一组不同的数据:电话号码、地址.... 对于这些集合中的每一个,我都有一个模型:PhoneNumber、Address。它们完全不同,但有一
我知道这两者有点相似,但两者之间肯定有任何内在差异, [anObject performSelector:@selector(thisMethod:) withObject:passedObject]
我想做performSelector:withObject:,但对象是CGFloat。所以它实际上不是一个对象。我怎样才能做到这一点? 我正在执行选择器的对象不是我的,我无法修改它。 例如 [xyz
我正在搞乱一些线程。现在考虑一下:我有一个主线程。我开始一个新线程。在它的入口点方法中,我想创建一个运行循环。现在文档告诉我我必须有一个输入源。否则我的运行循环会立即退出。坏的。好的。但除了我的 Pe
我想执行有几个参数的方法。有什么简单的方法可以一次通过其中的几个吗?有点像 [self performSelector:@selector(methodName) withObject:firstPa
我想执行有几个参数的方法。有什么简单的方法可以一次通过其中的几个吗?有点像 [self performSelector:@selector(methodName) withObject:firstPa
为了进行调试,我需要从一段代码中调用CGFloat访问器方法,该代码根据iVar的名称生成选择器。 - (CGFloat) myIVar { return myIVar; } 设置者具有以下形
我有一个自定义 BackBarButton,我有一个属性来存储在某些情况下可以更改的选择器。所以我不能很顺利地使用委托(delegate)。 在不将“工作流程”更改为委派的情况下,我该怎么做才能消除此
我收到 ARC 编译器的以下警告: "performSelector may cause a leak because its selector is unknown". 这就是我正在做的事情: [_
这可能是一个幼稚的问题,但我还是会问这个问题,因为我找不到任何文档来解决我脑海中的这个问题。 我使用 Xcode45-DP4 在设备和模拟器中运行 iOS5.1。 我有一个循环遍历一个类的多个实例的数
我在这段代码中使用 performSelector 方法时遇到了一些问题: 这个方法在另一个名为“JSONMethods”的类中: +(void)sendPostMsgWithMultipleArgu
背景:我有一个代表与服务器连接的对象(我们称之为 BackendClient)。它的方法生成为单个 @protocol 并且它们都是同步的,所以我想创建将在后台调用它们的代理对象。主要问题是返回值,我
我熟悉此 ARC 警告 ( performSelector may cause a leak because its selector is unknown ) 的解决方案,并在大多数情况下实现了它们
这行代码完美运行 [self explodeBomb:obj]; 但是如果我用下面的行替换它,我会得到一个 NSInvalidArgument 异常,原因是无法识别的选择器。 [self perfo
我在另一个类中有一个方法,我这样调用这个方法 [captureView performSelector:@selector(startRecording) withObject:nil afterDe
是否可以使用此方法并传递一个对象?使用此代码,我收到此错误: -[myApp hideUpdateView]: unrecognized selector sent to instance 0x8b6
我是一名优秀的程序员,十分优秀!