ios – NSInvocation和内存问题

参见英文答案 > NSInvocation getReturnValue: called inside forwardInvocation: makes the returned object call dealloc:3个
所以我来自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];

之后:没有内存问题,但我不确定我是否正确:

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);

解决了所有内存问题,而且看起来更简单.如果您发现此问题,请发表评论.

解决方法

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

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

>块:在上下文中定义,选择任何参数计数和类型,也可能存在内存问题.关于如何使用它们有很多资源.
> performSelector:最多2个对象参数,使用以下方法调用

[target performSelector:selector withObject:data withObject:args];

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

id returnValue = objc_msgSend(target,/* 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,arg1);

如果你的方法返回一个结构,事情会有点复杂.您可能(但并非总是)需要使用objc_msgSend_stret – see here for more info.

编辑: – 这行必须添加代码中,否则Xcode会抱怨:

#import <objc/message.h>

要么

@import ObjectiveC.message;

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...