简体   繁体   中英

Objective-C ARC and Instance Variables iOS SDK

Are we supposed to convert all of our instance variables we wish to retain to private properties or am I missing something obvious?

@interface SomethingElse : Something  {

    NSMutableArray *someArray;

}

In this example, someArray is initialized in a method with [NSMutableArray initWithObject:someObject] but isn't retained.

My particular situation is I'm updating a game, there are a lot of instance variables, so I want to make sure I'm doing this right for the sake of future versions of the sdk.

Are we supposed to convert all of the local variables we wish to retain to private properties or am I missing something obvious?

First, the variable you showed in your example is an instance variable, not a local variable. Local variables are declared inside a block of code (eg inside a function or method, or inside some sub-block such as the body of a conditional statement) and have a lifetime that's limited to the execution of the block in which they're declared. Instance variables are declared in a class; each instance of that class gets its own copy of the instance variables declared by the class.

Second, no, you don't need to convert all your instance variables to properties. Instance variables are treated as strong references by default under ARC. A property is really just a promise that a class provides certain accessors with certain semantics. Just having an instance variable doesn't mean that you have to provide accessors for that ivar. (Some might say that you should , but you don't have to.)

A @property is the same as an instance variable unless you use other than the default storage modifier, which is strong for objects. Example, if you want @property (copy) NSString *s; either use an instance variable and remember to call copy each time you set the variable, or use the @property (which is easier).

ARC's version of retain is called strong .

Basically, you would declare it using something like:

@property (strong) NSMutableArray *someArray;

See What does the "strong" keyword do for details.

It's generally better to use properties instead of local variables, because the properties get you accessors/setters for "free", and are generally easier to use.

You describe a BAD_ACCESS problem in some of your other comments. There is something else going on here. In ARC, your ivars are strong unless otherwise qualified (and in non-ARC, they're not going to get released on your behalf).

For example, this ARC code works fine, with no BAD_ACCESS as you report in your comments to other answers:

@interface ArcTestViewController ()
{
    NSMutableArray *_someArray;
}
@end

@implementation ArcTestViewController

- (void)dealloc
{
    _someArray = nil;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    _someArray = [[NSMutableArray alloc] initWithObjects:@"Mo", @"Larry", @"Curly", nil];
}

- (IBAction)checkIvarTouchUpInside:(id)sender 
{
    NSLog(@"%s _someArray = %@", __FUNCTION__, _someArray);
}

@end

You might have to show us your example where you're getting your BAD_ACCESS because it has to be something else.

In answer to the "property" or "ivar" question, while I'm sympathetic to the "always use properties" argument, personally I use properties for anything for which I need to provide external accessors and I otherwise use private ivars (not in the .h, but rather in the private interface in the .m file). This makes my public interfaces in my .h files really clean and easy to understand when I return to them months later. If you do adopt a "always use properties" approach, I'd only advise that your public declaration of those properties should be as restrictive as possible (make the property private if you can, make the public declaration of the property readonly if you don't need to provide readwrite access, etc.).

By the way, the Naming Properties and Data Types of the Coding Guidelines for Cocoa is a good reference of best practices.

With Obj-C 2.0 and later, there really seems to be little reason to use iVars. I personally haven't used one in forever. The properties just do everything for you!

Thanks all for your responses.

If I call the method that needs the object with (using a cocos2d game engine method):

[self schedule:@selector(someMethod) interval:3.0];

The object is dereferenced, if I call it directly without putting it in the cocos2d scheduler:

[self someMethod];

Then there is still a valid pointer. Just to test, I retained it and it stays around.

So the question is now how do we force a retain to prevent ARC from thinking we're done with it and releasing it?

Changing the instance variable to a private property does it safely so we'll go with this as the answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM