0

Every few months I try to re-learn Cocoa because I have no real use for programming iOS other than as a hobby. I'm going back over the basics and looking at what's different with the dot notations; for instance, seeing how the API has been updated to do common tasks by default.

There is plenty of documentation, which is good, but can also be a bad thing when you want to get up and running quickly. While it is slowly coming back, I consider myself a born-again neophyte on the subject, so any help is appreciated.


header file:

@interface FooClass : NSObject
{
@private
    double foo;
}
@property (nonatomic) double foo;
@end

implementation file:

@implementation FooClass
@synthesize foo = _foo;
- (void) doSomething
{

}
@end

Inside the doSomething implementation, is it possible to have a local variable (e.g. bar) that is a pointer to the class's foo, such that when bar is get/set foo is updated (local alias)? I've tried variations of:

double bar = *self.foo;
double *bar = self.foo;
double *bar = *self.foo;
double *bar = &self.foo;

bar=5;

If so, what's the right syntax? Also, something is telling me this is a bad idea, so why might it be?


Edit: It looks like after some more searching I found something similar: objective-c: double pointers to property not allowed? Now, I'll try to make sense of it.

Community
  • 1
  • 1
vol7ron
  • 40,809
  • 21
  • 119
  • 172
  • @Rob: I liked your first (deleted) comment better. Especially since your "no offense" invites unnecessary down ratings. I realize there is a mistake, hence the reason for bringing it here, but you should realize it was mostly once valid syntax and was not a mistake a couple years ago (aside from some new additions). – vol7ron Dec 18 '12 at 02:36
  • No worries, I appreciate all the help. I was once a regular in the IRC channel, but thought this was a simple enough question to post on SO. It looks like I'm not going to be able to rely on the iTunesU video or my old iOS Programming books and will have to instead read the documentation. Thanks again – vol7ron Dec 18 '12 at 02:43
  • The use of the explicit ivar was perfectly valid syntax, just not common practice any more. It's no longer required and therefore best practice is to omit it, but it's not a deal breaker. If you have old code that uses that pattern, that's fine. The serious problem is the use of the `@synthesize` statement that synthesizes an ivar of a different name, which only illustrates why we don't use explicitly declared ivars any more. I've helped more than one person on S.O. track down a bug that was caused by precisely that mistake, which is why I react to it so strongly. – Rob Dec 18 '12 at 02:45
  • The confusion was in the documentation I found. Where one version suggested that `@synthesize foo;` used `foo` as an ivar. As per the video, I was trying not use the same name for the instance variable as the property (changing the `foo` to `_foo`). – vol7ron Dec 18 '12 at 02:52
  • This looks like a basic C question? Go read about pointers and addresses. – Ken Aspeslagh Dec 18 '12 at 04:29
  • @KenAspeslagh: but it's not. Basic C is understandable, Cocoa is Apple's implementation of objective C that has it's own flair and acts differently behind the scenes. Go read about Cocoa. I'll elaborate; the example trial and errors is not due to lack of understanding of what a pointer/mem-address is, but more the correct way to implement in Cocoa and SO guidelines suggest to display what has been attempted. – vol7ron Dec 18 '12 at 05:03
  • 1
    @Rob: After watching some of this WWDC video from the link you gave below, I see what you're saying now about how synthesize is no longer needed - neat stuff! – vol7ron Dec 18 '12 at 05:04
  • 1
    The fact that this was closed after an answer was given is hilarious. Especially since it was closed by one of the people that answered the question. The question is cut-and-dry and has an answer that does not `solicit debate, arguments, polling, or extended discussion` If you think it should be closed, you should post a comment on how it could be improved to not satisfy one of those demands – vol7ron Dec 18 '12 at 08:19
  • I don't like the system-provided description for "not constructive" as it focuses on meta issues. The question suffers more fundamental problems: The question's premise, to have a local var for a property, is not a constructive notion and is inadvisable. And as to why I would answer a question that I voted to close, I did so because the question's introduction contains code with an insidious bug that has plagued many developers and it is irresponsible to leave that uncorrected. But if you want to vote to reopen the question, you should do so. – Rob Dec 18 '12 at 14:59
  • @Rob: but whether it was advisable or not, was also part of the question (reasons for it being a bad idea), which I guess could suggest argumentation or cause for debate; but given the code, it was less an open-ended question and more a plea for clarity. Regardless, I still thank you for your answer and the reason that you had just stated is why I would have left it open, rather than vote to close - whatever's best for the community – vol7ron Dec 19 '12 at 17:55
  • @vol7ron Understood. You can always post a link to this on [Meta](http://meta.stackoverflow.com/) and solicit feedback from there, too, if you'd like. That's the right place to debate the pros and cons regarding reopening a question. You'll get feedback from a broad array of people there. Regardless, my apologies if this caused any hard feelings. – Rob Dec 19 '12 at 19:12
  • @Rob: no way, good criticism is fine and I received my answer :) I admit, I've been breaking my own rules about using these comments as a medium for discussion, which I don't think is what it should be used for, but since you and I are the only ones that have really contributed to this thread (and it's closed), sometimes I can break my own rules. - I've been doing more scripting lately (Perl/Ruby) and so just doing a little bit of reading (and video watching) has already brought me back to the swing of things. -- thanks again – vol7ron Dec 19 '12 at 23:25

1 Answers1

2

Your example contains a mistake:

@interface FooClass : NSObject
{
@private
    double foo;
}
@property (nonatomic) double foo;
@end

This declares a property foo. It also declares an ivar (instance variable) foo, which one might assume was the ivar associated with the property of the same name.

@implementation FooClass
@synthesize foo = _foo;
@end

Unfortunately, the @synthesize statement says "synthesize the foo property and create an ivar called _foo for it." So, you now have two ivars, foo (which you created between the {} in the @interface), and _foo, which you just synthesized as the ivar associated with the foo property. That's not good that that you have the foo ivar floating out there, which was explicitly declared, leading the reader to assume that it would be associated with the property of the same name, but it's not, because _foo is.

Long ago, you would have been advised to fix your explicit ivar declaration, e.g.

@interface FooClass : NSObject
{
@private
    double _foo;
}
@property (nonatomic) double foo;
@end

But even better now, it's advised that you omit the explicit ivar definition for a property altogether, and let the @synthesize statement create that ivar for you, eliminating any possibility of the problems we describe above, e.g., simply:

@interface FooClass : NSObject
@property (nonatomic) double foo;
@end

Furthermore, the @synthesize statement is now optional, and if omitted, it will end up doing precisely what you suggested @synthesize foo = _foo;.

And in answer to your question about about having a variable to access your property, that's what the _foo instance variable is. Why do you need another variable? And, besides, you should generally use the getter.

It's generally advisable to not use the ivar for setting the property, but rather use the property's accessor. This counsel would apply to any attempts to change the value of the property through a local variable, too. The only time you absolutely should be using the ivar is in your initializer and dealloc methods.

By the way, that reference to "Use Accessor Methods to Set Property Values" is a roundabout answer to your main question (at least if you were ever tempted to use that local variable to change the value of the property). You should only be using the object setter accessor for changing a property's value. The setter does important stuff that it would be unwise to bypass. To answer your final question would be, in effect, instructing you how to do the wrong thing in a way that doesn't generate a compiler warning, and thus I hesitate to go there.

Some relevant references include:

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • The documentation I found varied. One said `@synthesize foo;` would create an instance variable of `foo` another said it would create `_foo`. So, I thought being specific wouldn't hurt. – vol7ron Dec 18 '12 at 02:00
  • I'm trying to reuse old code to determine what's changed, but I admit, I'm also trying to do some new things too, which is a bad idea when re-learning (and I may have tried to do the same thing before - who knows?). In any case, I'm not sure why I set a private variable to the class, but if I keep the `{...}` (I have other un-related definitions there) and remove the declaration, will it still work? – vol7ron Dec 18 '12 at 02:03
  • I didn't touch on the private variable in your class, but the emerging convention is to define those in the [private class extension](http://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html#//apple_ref/doc/uid/TP40011210-CH6-SW3) in your .m file. – Rob Dec 18 '12 at 02:28
  • If you're working with old code, you'll have to make up your mind, but my answer above pretty much summarizes current conventional thinking (have property, synthesize ivar using underscore, don't declare the ivar for properties explicitly, use setter when changing properties, etc.). In terms of how much of the old practices you want to excise from old code, that's up to you. I'm pretty aggressive in cleaning up old if I have to touch the code for any reason, because it generally only makes it easier to maintain, but it's completely up to you. – Rob Dec 18 '12 at 02:32
  • I'm taking your above advice. As stated, I'm re-learning this and am going through my old example programs (like the iTunes University's Stanford Calculator), and cleaning them up. – vol7ron Dec 18 '12 at 02:35
  • By the way, cleaning up old ivar names, I think the [Edit All In Scope](http://developer.apple.com/library/mac/#recipes/xcode_help-source_editor/EditAll/EditAll.html) feature in Xcode is brilliant. I love it and once you get used to a few of it's idiosyncrasies, it's brilliant. – Rob Dec 18 '12 at 02:35
  • Part of my dilemma, and the origination for the question, is that there are a bunch of `self.propName`s in a method. I was hoping to shorten that, mainly removing the `self`. Is your suggestion that I should not use the instance variable `_propName` and still use the dot notation, despite it cluttering up the code? – vol7ron Dec 18 '12 at 02:41
  • @vol7ron Personally, I'd stick with the accessor methods. And absolutely keep it for the setter (for KVO and memory compliance reasons). I would even stick with the accessor for the getter, too, personally, but that last point is a little less black and white. If you want to clean up your code, you should check out WWDC 2012 [Modern Objective-C](https://developer.apple.com/videos/wwdc/2012/?id=405) and [Migrating to Modern Objective-C](https://developer.apple.com/videos/wwdc/2012/?id=413). If you want clean code, Xcode 4.5 introduced some cool features that I love (and others don't). – Rob Dec 18 '12 at 02:52
  • 1
    @vol7ron: “One said `@synthesize foo;` would create an instance variable of `foo` another said it would create `_foo`.” Probably not; the truth is that `@synthesize foo` will create an instance variable named `foo`, whereas *implicit* synthesis (i.e., not saying `@synthesize foo` at all) will create an instance variable named `_foo`, the same as if you had said `@synthesize foo = _foo;`. – Peter Hosey Dec 18 '12 at 09:15
  • What I was reading was http://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html#//apple_ref/doc/uid/TP40011210-CH5-SW6] and I think you're right. It wasn't clear that the synthesis was implicit; or I missed that part. It all makes sense now. – vol7ron Dec 18 '12 at 10:52