首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSInvocation和内存问题

NSInvocation和内存问题
EN

Stack Overflow用户
提问于 2013-07-07 14:01:27
回答 2查看 2K关注 0票数 8

因此,我来自Java世界,在那里,我们对内存管理问题一无所知。在很大程度上,ARC救了我的命,但这里有一些东西让我感到困惑。基本上,我正在使用NSInvocations做一些事情,在我进行以下代码修改之前,我遇到了一些严重的内存问题。自从我做了这些修改,内存崩溃已经消失了,但我通常非常害怕我不理解的代码。我这样做对吗?

之前:各种内存问题:

代码语言:javascript
复制
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 :没有内存问题,但我不确定我是否正确:

代码语言:javascript
复制
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:

代码语言:javascript
复制
NSString * returnValue = objc_msgSend(target, selector, data, arg);

它解决了所有的内存问题,而且看起来更简单。如果您在此看到任何问题,请发表评论。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-07 15:16:46

我会这样回答你的问题:不要使用 NSInvocation**.**,这只是一个友好的建议,如果可能的话,请避免这种情况。

在Objective-C中有很多很好的回调方法,这里有两个可能对你有用:

  • Blocks:在上下文中定义,选择任何参数计数和类型,也可能与内存有关的问题。有许多关于如何使用them.
  • performSelector:最大2对象参数的资源,通过以下方式调用:

目标性能选择器:带有对象的选择器:data withObject:args;

此外,当我需要调用一个带有4个参数的选择器时,我仍然不使用NSIvocation,而是直接调用objc_msgSend

代码语言:javascript
复制
id returnValue = objc_msgSend(target, selector, data, /* argument1, argument2, ... */);

很简单。

编辑:使用objc_msgSend时,您需要小心处理返回值。如果你的方法返回一个对象,使用上面的代码。如果它返回一个基本类型,您需要强制转换objc_msgSend方法,以便编译器知道发生了什么(see this link)。下面是一个接受一个参数并返回BOOL的方法的示例:

代码语言:javascript
复制
// 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编辑:-必须将这一行添加到代码中,否则会报错:

代码语言:javascript
复制
#import <objc/message.h>

代码语言:javascript
复制
@import ObjectiveC.message;
票数 5
EN

Stack Overflow用户

发布于 2013-07-07 15:06:14

在可能的情况下,您通常应该将块视为更好的替代方案(它们取代了NSInvocation)。

至于返回值,您可以使用以下代码:

代码语言:javascript
复制
CFTypeRef result = NULL;
[invocation getReturnValue:&result];    
NSString *returnValue = (__bridge NSString *)result;

这里的基本问题是-getReturnValue:不返回out对象,就ARC而言。因此,它很可能会错误地执行引用计数操作(编译器会在ARC中为您添加这些操作),因为-getReturnValue:的参数是void*,而不是out对象(例如NSObject**)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17509702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档