因此,我来自Java世界,在那里,我们对内存管理问题一无所知。在很大程度上,ARC救了我的命,但这里有一些东西让我感到困惑。基本上,我正在使用NSInvocations做一些事情,在我进行以下代码修改之前,我遇到了一些严重的内存问题。自从我做了这些修改,内存崩溃已经消失了,但我通常非常害怕我不理解的代码。我这样做对吗?
之前:各种内存问题:
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[target class] instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:target];
[invocation setArgument:&data atIndex:2];
[invocation setArgument:&arg atIndex:3];
[invocation invoke];
NSString *returnValue;
[invocation getReturnValue:&returnValue];After :没有内存问题,但我不确定我是否正确:
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[target class] instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:target];
[invocation setArgument:&data atIndex:2];
[invocation setArgument:&arg atIndex:3];
[invocation invoke];
CFTypeRef result;
[invocation getReturnValue:&result];
if (result)
CFRetain(result);
NSString *returnValue = (__bridge_transfer NSString *)result;编辑:
我只是想在下面的答案的基础上补充一下,我使用的是objc_msgSend:
NSString * returnValue = objc_msgSend(target, selector, data, arg);它解决了所有的内存问题,而且看起来更简单。如果您在此看到任何问题,请发表评论。
发布于 2013-07-07 15:16:46
我会这样回答你的问题:不要使用 NSInvocation**.**,这只是一个友好的建议,如果可能的话,请避免这种情况。
在Objective-C中有很多很好的回调方法,这里有两个可能对你有用:
目标性能选择器:带有对象的选择器:data withObject:args;
此外,当我需要调用一个带有4个参数的选择器时,我仍然不使用NSIvocation,而是直接调用objc_msgSend:
id returnValue = objc_msgSend(target, selector, data, /* argument1, argument2, ... */);很简单。
编辑:使用objc_msgSend时,您需要小心处理返回值。如果你的方法返回一个对象,使用上面的代码。如果它返回一个基本类型,您需要强制转换objc_msgSend方法,以便编译器知道发生了什么(see this link)。下面是一个接受一个参数并返回BOOL的方法的示例:
// Cast the objc_msgSend function to a function named BOOLMsgSend which takes one argument and has a return type of BOOL.
BOOL (*BOOLMsgSend)(id, SEL, id) = (typeof(BOOLMsgSend)) objc_msgSend;
BOOL ret = BOOLMsgSend(target, selector, arg1);如果你的方法返回一个结构,事情就有点复杂了。您可能(但并非总是)需要使用objc_msgSend_stret -- see here for more info。
Xcode编辑:-必须将这一行添加到代码中,否则会报错:
#import <objc/message.h>或
@import ObjectiveC.message;发布于 2013-07-07 15:06:14
在可能的情况下,您通常应该将块视为更好的替代方案(它们取代了NSInvocation)。
至于返回值,您可以使用以下代码:
CFTypeRef result = NULL;
[invocation getReturnValue:&result];
NSString *returnValue = (__bridge NSString *)result;这里的基本问题是-getReturnValue:不返回out对象,就ARC而言。因此,它很可能会错误地执行引用计数操作(编译器会在ARC中为您添加这些操作),因为-getReturnValue:的参数是void*,而不是out对象(例如NSObject**)。
https://stackoverflow.com/questions/17509702
复制相似问题