使ObjectiveC对象在函数范围之外有效 [英] Keeping objectiveC object valid outside the scope of a function

查看:72
本文介绍了使ObjectiveC对象在函数范围之外有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在设置作为输入指针的变量时,我对ARC的行为有些困惑,并期望在函数范围之外保持有效.

I'm a bit confused about ARC behaviour when setting variable that is an input pointer, and is expected to remain valid outside function scope.

考虑以下使用openDirectory框架的示例.

considering the following example that uses openDirectory framework.


@interface bbb
-(bool)doSomethingWithADRecord:
-(void)obtainADRecord(NSString*)user
-(NSString*)getADrecord:(ODAttributeType)attr fromRecord:(ODRecord*)record;
@end 

@interface bbb {

    ODRecord *_myRecord;
}
@end 


@implementation bbb
-(void)doSomethingWithADRecord:
{
     // here we access _myRecord and expect it to be valid.
}

-(bool)obtainADRecord:(NSString*)user
{
    ...
    // here I call the method that will set the member _myRecord from type ODRecord*
    // whose scope related to the lifespan of the containing class (bbb)
    [self getADrecord:attr toRecord:_myRecord];

}

// the following function should set the variable record to be used by the caller. 
-(NSString*)getADrecord:(ODAttributeType)attr fromRecord:(ODRecord*)record {
    ...
    // here a set an ODQuery object.
    ODQuery *query = [[ODQuery alloc] initWithNode ... 

    // queryResults is an array of items from type ODQuery* 
    NSArray* queryResults = [query resultsAllowingPartial:NO error:&err];

    for(ODRecord *item in queryResults) {
        if (/*some logic*/)
        { 
            //option 1: just regular set operator, expecting the ARC will do the retain itself 
            record = item;

            //option 2: explicits take a reference on that item.  
            record = [[item retain] autorelease];
            return @"found item";
        }
    }
}
@end

为澄清我的问题,我想知道我上面提到的2个选项中哪个是正确的,就将引用传递给record并最终传递给_myRecord而言,因此它将存储正确的值即使queryResults的临时列表也将被清除.

To Clarify my question, I seek to know which one of the 2 options I stated above is the correct one , in terms of passing the reference to record and eventually to _myRecord, so it will store the correct value even after the temporal list of queryResults will be cleaned.

请注意,在这两个选项中,我都只是设置指针值,而无需从类型ODquery初始化新对象并将数据复制到该新对象.

Notice that in both options I simply setting the pointer value without initiate new object from type ODquery and copying the data to this new object.

谢谢!

推荐答案

我想知道简单地执行record = item是否足以使该对象指向的数据持续超出函数getADrecord

I'd like to know whether simply doing record = item will be enough for the data pointed by this object to last beyond the scope of the function getADrecord

您误解了参数的工作方式;参数,例如record,本质上是一个局部变量,该局部变量被初始化为调用中传递的 value .

You are misunderstanding how parameters work; a parameter, such as record, is essentially a local variable which is initialised to the value passed in the call.

因此,对record的对象引用的 any 分配对超出getADrecord范围的被引用对象的生存期将产生零影响,因为record对于该函数而言是本地的.

Therefore any assignment of an object reference to record will have zero effect on the lifetime of the referenced object outside of the scope of getADrecord as record is local to the function.

要通过参数返回类型T的值,该参数的类型必须为指向类型T的变量的指针".一个具有简单值类型的示例:

To return a value of type T via a parameter the type of the parameter must be of type "pointer to a variable of type T". An example with a simple value type:

- (void) add:(int)value           // an int value
          to:(int *)ptrToVariable // a pointer to an int variable
{
   // note the need to indirect (`*`) through pointer stored in
   // `ptrToVariable` to access the pointed at variable
   *ptrToVariable = *ptrToVariable + value; 
}

int x = 31;
[self add:11 to:&x]; // &x creates a pointer to the variable x
// x = 42 after call

现在,您不想返回简单的值类型,而是返回一个对对象的引用的值,并且希望ARC正确管理生存期.这有点复杂.

Now you don't want to return a simple value type but a value which is a reference to an object and you wish ARC to manage the lifetime correctly. This is a little more complicated.

在ARC下,保存对对象的引用的变量既具有类型又具有 ownership属性;此属性通知ARC如何处理在变量中存储引用.通用所有权属性为__strong__weak,不带显式属性__strong.因此,您的实例变量声明是以下内容的简写:

Under ARC a variable which holds a reference to an object has both a type and an ownership attribute; this attribute informs ARC how to handle storing references in the variable. The common ownership attributes are __strong and __weak, without an explicit attribute __strong is assumed. So your instance variable declaration is shorthand for:

ODRecord __strong *_myRecord;

此声明意味着,对于存储在_myRecord ARC中的ODRecord的任何引用,只要存在_myRecord且不存在该引用,该引用的ODRecord生存时间至少被其他引用或nil覆盖.只要同一参考可以存储在其他地方,它至少要长",这也会影响生命周期.

This declaration means that for any reference to an ODRecord stored into _myRecord ARC will keep the referenced ODRecord alive at least as long as _myRecord exists and the reference is not overwritten by a different reference or nil. It is "at least as long" as the same reference could be stored elsewhere and these will also effect the lifetime.

快到了!要通过参数返回对ODRecord的引用,该参数的类型必须为指向ODRecord的强引用类型的变量的指针,即:

Almost there! To return a reference to an ODRecord via a parameter the type of the parameter must be "pointer to a variable of type strong reference to ODRecord, i.e.:

- (NSString *)getADrecord:(ODAttributeType)attr
               fromRecord:(ODRecord * __strong *)record

现在是一个作业,例如:

now an assignment such as:

*record = item;

将导致对指向变量的赋值,并且由于该变量的类型为ODRecord __strong *,ARC将确保所引用的ODRecord的生存时间至少要长于对它的引用存储在所指向的变量中.变量.

will result in an assignment to the pointed-at variable and as that variable is of type ODRecord __strong * ARC will ensure the referenced ODRecord will live at least as long as a reference to it is stored in the pointed-at variable.

您对此方法的调用必须将指针传递给您的变量:

Your call to this method must pass a pointer to your variable:

[self getADrecord:attr toRecord:&_myRecord];

注释:

  • "out"参数在Objective-C中不经常使用,但显着的错误返回例外–它们的类型为NSError * _autoreleasing *,Apple将此用法称为回写回叫".

  • "out" parameters are not often used in Objective-C with the notable exception of error returns – these are of type NSError * _autoreleasing * and Apple names this usage as "call-by-writeback".

有关ARC和通过参数返回值的更详细说明,请参见 NSError和__autoreleasing

For a deeper explanation of ARC and returning values via parameters see Handling Pointer-to-Pointer Ownership issues in ARC and NSError and __autoreleasing

重要:

正如@matt在注释中指出的那样,您的代码包含ARC中禁止的retainautorelease调用,因此,如果您的代码正在编译,则您未启用ARC.对于新项目,将启用ARC,对于现有项目,您可能需要将其启用为项目的 Build Settings ,该设置称为"Objective-C自动引用计数".

As pointed out by @matt in the comments your code contains retain and autorelease calls which are forbidden in ARC and therefore if your code is compiling you DO NOT have ARC enabled. For new projects ARC will be enabled, for existing projects you may need to enable it your project's Build Settings, the setting is called "Objective-C Automatic Reference Counting".

这篇关于使ObjectiveC对象在函数范围之外有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆