0

Suppose I have this code...

foo.h

@interface Foo : NSObject {
    NSString *aString; // 1   
}

@property (nonatomic, retain) NSString *aString;

foo.m

@synthesize aString = _aString;


....

- (void)dealloc {
    [aString release];
    [super dealloc];
}

My questions are:

  • do I really need to declare aString in "1"? (see code)
  • if I am synthesizing aString = _aString, I am already creating an instance variable, right?
  • if I am retaining the property on foo.h (@property), why Xcode complains if I release aString in dealloc?

thanks.

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
Duck
  • 34,902
  • 47
  • 248
  • 470

6 Answers6

3

You are mixing up the property and the backing variable. "aString" is the property, which you access via method call (e.g. [self aString]). "_aString" is the backing variable, which you access directly (e.g. _aString).

Taking your questions in order:

  • No. This is an unused variable because you told the compiler to use _aString as the variable. (You don't actually need to declare either one in the modern run-time.)

  • Yes, as indicated in my answer to the first question.

  • Because the compiler expects you to send a message to an object, and "aString" is undefined as written. Normally you would use [self aString] to access the object, but this is a special case: in -dealloc and in -initXYZ you don't use accessor methods because of potential side effects. Switch to [_aString release] and everything will work (unless you have ARC, in which case you don't release at all.

Conrad Shultz
  • 8,748
  • 2
  • 31
  • 33
  • ah, I see, a string is a kind of alias to the real stuff... :D ... thanks. Your answer was perfect!!!!!! – Duck Jan 18 '12 at 16:40
  • The compiler is doing a few more things for you behind the scenes. I wrote up a detailed response (http://www.cocoabuilder.com/archive/cocoa/312413-code-error-in-your-first-mac-app-tutorial.html#312424) for someone on the cocoa-dev mailing list a while back if you want to understand properties better. – Conrad Shultz Jan 18 '12 at 16:50
0

With your @synthesize, the instance variable (your "1") should be NSString* _aString.

The reason you use synthesize with a differently named variable is so that you always use self.aString to properly release the old object instead of accidentally overwriting the pointer by directly modifying aString.

Do you have ARC enabled? If so, that's why Xcode complains about releasing it.

Tim
  • 14,447
  • 6
  • 40
  • 63
  • no I don't have arc enabled. This is a project targeted to iOS 4.2. Regarding the declaration of _aString on "1", I agree that is logical, but why many authors do not do that? I have seen a lot of projects where the guy just declares it at @property and synthesizes. – Duck Jan 18 '12 at 16:36
0

To answer your questions in order:

  • No. There might some sort of "best-practice" reason that I'm missing, but @property will synthesize the instance variable as well.
  • When you declare aString = _aString, what that allows you to do is directly manipulate _aString without accessing the synthesized getter/setter (by calling _aString) or use the synthesized getter/setters (by calling self.aString).
  • You are likely releasing it somewhere else, someone else is over-releasing it, or you're using ARC. With NSStrings (and other simple objects that have deep copy method readily available), I find it best to use @property (copy), and _aString = [stringPassedToInit copy], so that you are the only one handling your string's retain count. If you're using ARC, you don't need to worry about retain/release in most instances.
Patrick Perini
  • 22,555
  • 12
  • 59
  • 88
0

No, you don't need to declare ivars any more (since iOS 3 I think). You can delete the entire { ... } part of your interface declaration and it won't make any difference.

It's complaining because your ivar is named _aString, not aString. You need to say

[_aString release]

instead.

Nick Lockwood
  • 40,865
  • 11
  • 112
  • 103
  • no, I am not using ARC. You mean I don't need to declare ivars for properties, right? the other ivars I have to declare... – Duck Jan 18 '12 at 16:36
  • Yes, if you synthesize a property, you don't need to declare the ivar for it. You can use properties for everything and not use ivars at all, which is best practice. If you want your properties to be private, declare them inside a private interface within your .m file instead of in your .h file. – Nick Lockwood Jan 18 '12 at 16:41
-1

Answers : -

do I really need to declare aString in "1"? (see code) - Now with iOS 4 onwards you won't need to declare.

if I am synthesizing aString = _aString, I am already creating an instance variable, right? - Yes

if I am retaining the property on foo.h (@property), why Xcode complains if I release aString in dealloc? - now you need to use this - self.aString = nil, this will take care.

rishi
  • 11,779
  • 4
  • 40
  • 59
  • 1
    Wrong answer. DO NOT use accessors in dealloc - e.g. self.aString = nil. This may have unintended consequences. – Ashley Mills Jan 18 '12 at 16:34
  • Correct. Never use accessors in dealloc or init. – Conrad Shultz Jan 18 '12 at 16:38
  • Why Downvote, while the same is mentioned in apple's Objective-C 2.0, p74 - If you are using the modern runtime and synthesizing the instance variable, however, you cannot access the instance variable directly, so you must invoke the accessor method. You can check out this and tell me where am i wrong. – rishi Jan 18 '12 at 16:38
  • But with iOS 4.0 if we are not declaring instance variable then how to access that? – rishi Jan 18 '12 at 16:40
  • You declare it by writing the @synthesize. The synthesize creates an ivar. – Nick Lockwood Jan 18 '12 at 16:43
  • So when you say that apple docs are incorrect then there is no point in discussion. – rishi Jan 18 '12 at 16:44
  • @NickLockwood that i know, but what about the apple objective c 2.0 pdf, if that is not correct then what is correct? This is my main point? – rishi Jan 18 '12 at 16:47
  • @AshleyMills - I just want to know if apple doc is wrong then what should i follow? – rishi Jan 18 '12 at 16:53
  • @ConradShultz- I just want to know if apple doc is wrong then what should i follow? – rishi Jan 18 '12 at 16:53
  • I didn't downvote, but I'm curious. I don't know what the "Objective-C 2.0 pdf" is, but the closest thing I have is the document titled "The Objective-C Programming Language," which doesn't seem to have the snippet you quoted. Can you point me more explicitly to what you are reading? – Conrad Shultz Jan 18 '12 at 16:58
  • From Apple's docs "Don’t Use Accessor Methods in Initializer Methods and dealloc" - http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW6 – Ashley Mills Jan 18 '12 at 17:03
  • @ Conrad Shultz and @AshleyMills Check out this thread then -http://stackoverflow.com/questions/5621139/is-there-any-problem-using-self-property-nil-in-dealloc – rishi Jan 18 '12 at 17:30
  • 2
    The reasons for not using accessors in dealloc are sensible (don't call methods that might be overridden by a subclass and cause problems if executed at dealloc time) whereas the reason for doing it (because you can't access synthesised ivars directly) is demonstrably false. – Nick Lockwood Jan 18 '12 at 18:27
-1

My answers are:

  • NO
  • YES
  • Try [_string release] instead.
Ashley Mills
  • 50,474
  • 16
  • 129
  • 160