Proper way to perform additional code when setting properties - objective-c

This might seem like a basic question but I'm still getting a handle on properties so please bear with me.
I have a custom NSView subclass that does its own drawing. I've set up support for different styles with a #property for setters and a typedef enum for human-readable integers. It works great, but the view won't redraw after setting its style unless I manually call setNeedsDisplay:YES on the control or resize its parent window.
Logically one would think the solution would be to simply do a [self setNeedsDisplay:YES] in the classes' setStyle: method, but I cannot for the life of me figure out how to properly do it. Whenever I try to override setStyle: it just complains, "Writable atomic property 'style' cannot pair a synthesized getter with a user defined setter".
What should be done in this situation?

Ideally, you would just declare your actual ivar/storage as a private property, then manually implement the setter setStyle:. In the implementation of setStyle:, set your private property/state, and perform your updates. So you just abstract the data from the client's interface. There are other ways to approach this, such as directly setting the ivar.
So an implementation may take the form:
MONThing.h
#interface MONThing : NSObject
- (void)setStyle:(t_style)pStyle; // << the client's interface
#end
MONThing.m
#interface MONThing ()
#property (nonatomic, assign, readwrite) t_style userStyle; // << the actual storage
#end
#implementation MONThing
- (void)setStyle:(t_style)pStyle
{
// validate parameter
// set our data
self.userStyle = pStyle;
// perform effects
[self setNeedsDisplay:true];
}
Over time, you will learn multiple ways to accomplish this, and when you would favor one over the other.

If you a setting your own setter then do not use #synthesize and #property. These are for automatic creation of the setter and getter methods. Declaring the variable in the interface file is enough.

Take a look at this question. To copy over the answer from the other question:
If you declare a #property to be atomic then do one of the following:
use #dynamic or;
use #synthesize and keep the synthesized setter and getter or;
provide a manual implementation of both the setter and the getter (without using one of the above directives).

Related

Objective C: I need some advice regarding properties vs ivars

I looked up my current problem on stackoverflow and many other website outlets, but I am a little confused to be quite honest. Should I only use properties when another class needs access to it and ivars when it is being used for only my private class? This is what I am getting so far, although I did hear some other things about when to use ivars and properties. I am just trying to keep my code clean and more modern. Any clarification will be appreciated.
This is a very opinion based topic. So I'm trying to stay with uncontroversial facts and advice:
Never access ivars from outside of the class. Public access would always be done through properties and their accessors or other methods. Nowadays headers should never contain ivar declarations.
Using ivars internally is possible and not uncommon. ARC makes this easy for object types, as ownership is handled automatically.
Using properties gives you proper ownership handling for NSString, NSArray et al. (copy).
Also, in some cases they can help with thread safety (atomic).
Using properties internally could make KVO compliance or other side effects easier to implement.
Using private properties is the standard pattern for exposing IBOutlets.
Properties can be queried during runtime. This is seldom needed, though.
Private properties have the problem of polluting the method namespace for a class. Unintentional overrides can occur.
The actual decision whether or not to use ivars in the implementation is a matter of personal preference. It is affected by many subtle details from code style.
In my opinion - you should only use properties, which are backed by an ivar if you didn't override the getter and the setter.
You should declare them in the public interface to make them public, and declare them in the private interface, that's right, to make them private.
There are many advantages to this, some are:
Perform lazy instantiation in the getter
Do validation in the setter
Make a property readonly public and readwrite privately
Within your class, you should almost always access your properties through the getter/setter unless:
You want to avoid the behavior you implemented in these methods (lazy instantiation, validation)
You are in the initializer
You are in the getter/setter
Here's an example of how of some of the following points:
#interface SomeObject : NSObject
#property (strong, nonatomic) NSMutableArray * objects;
#property (readonly, nonatomic, getter=isActive) BOOL active; // Public read-only
#end
#interface SomeObject()
#property (readwrite, nonatomic, getter=isActive) BOOL active; // Can be updated internally
#property (nonatomic, getter=isVisible) BOOL visible;
#end
#implementation SomeObject
- (NSMutableArray)objects {
if (!_objects) {
_objects = [NSMutableArray array]; // Lazy instantiate when first accessed
}
return _objects;
}
- (BOOL)isActive {
return _isActive && self.isVisible; // Cannot be active if not visible
}
- (BOOL)setActive:(BOOL)active {
self.visible = active; // Keep visibility same as active
_active = active;
}
-(BOO)setVisible:(BOOL)visible {
_visible = visible;
// perform animation or something else...
}
#end
Any of this cannot be achieved using ivars.
You should use declared properties inside and outside your class. Most developers say that you should only set the ivar behind a property in initializers. (I do not agree and use setters and getters in this case, too, but I'm in minority.)

My understanding of instance variables

I think I've been using Objective-C properties incorrectly. Specifically, I've been treating them like instance variables.
Here's an example of a recent interface:
// AIClass.h
#import "AIDataUtils.h"
#interface AIViewController : UIViewController
#property (strong, nonatomic) AIDataUtils *dataUtils;
#end
Then, in my implementation, I would use self.dataUtils as a way for any method in the class to easily access the same thing. No object from the outside would ever be interacting with that property.
What I'm realizing is that what I should have been doing is importing and declaring AIDataUtils in the implementation and not the interface. I think that would look like this:
// AIClass.m
#import "AIDataUtils.h"
#interface AIViewController ()
{
AIDataUtils *dataUtils;
}
#end
#implementation AIViewController
- (void)viewDidLoad
{
[super viewDidLoad];
dataUtils = [[AIDataUtils alloc] init];
...
}
The docs say:
Avoid explicitly declaring public instance variables. Developers should concern themselves with an object’s interface, not with the details of how it stores its data.
My understanding here is if another object has no business touching AIDataUtils, don't put it in the interface. The fact that a property exists in an interface should be a hint that you're supposed to feed or do something with that property.
Am I hot or cold?
My understanding here is if another object has no business touching AIDataUtils, don't put it in the interface.
You're right, but that doesn't mean that you can't keep using properties for internal values too -- just don't declare them in your public interface. Usually, using a class extension as you've suggested is a fine way to have your properties while still keeping internal things (more or less) private.
There was a period in the evolution of Objective-C when properties were very helpful in managing memory -- if you used a property's accessors everywhere, you could worry a lot less about when to retain and when to release something because the accessors would do that for you. Now that we have ARC, the memory management aspect of properties is less important, but a lot of us are still conditioned to use properties even for internal stuff. If nothing else, internal-only properties can make your code a little more consistent-looking.
If you intend dataUtils to be a private implementation detail, then you shouldn't declare it in the #interface in the header file.
Even if you want to keep it private, you can still make it a property in the .m file:
#interface AIViewController ()
#property (strong, nonatomic) AIDataUtils *dataUtils;
#end
Whether to make it a property or just an instance variable is a matter of taste and depends on how you use it. For example, if you only want to allocate the AIDataUtils instance lazily, you might as well make it a property and do the lazy allocation in the getter.
If you decide to make it an instance variable, there's probably no reason to declare it in a class extension. You can just declare it in the #implementation:
#implementation AIViewController {
AIDataUtils *dataUtils;
}
- (void)viewDidLoad {
[super viewDidLoad];
dataUtils = [[AIDataUtils alloc] init];
...
You can learn more about where to declare instance variables in this answer.

How do I make methods only available to properties in Obj-C?

I'm still new to Objective-C and I recently learned how to make properties, so far so good, but one thing that bothers me is that the setter and getter methods are still publicly available even after the property is made.
let's say I have the following code:
// myClass.h
#interface myClass : NSObject {
int _startPos;
}
#property (assign, readwrite, setter = setStartPos:, getter = getStartPos) int startPos;
-(void) setStartPos: (int) pos;
-(int) getStartPos;
#end
the implementation file should be rather self-explanatory, I'm not trying to do anything specific.
Now, I read somewhere, and tried it in practice that if you make a category in the implementation file, and add some methods to that, it's possible to make those methods invisible (aka private) to things outside of the myClass.m file.
"Alright" I think, and decide to try it out:
//myClass.m
#import <Foundation/Foundation.h>
#import "myClass.h"
#interface myClass (hidden)
-(void) setHiddenStartPos: (int) hPos;
-(int) getHiddenStartPos;
#end
#implementation myClass (hidden)
-(void) setHiddenStartPos: (int) hPos {
_startPos = hPos;
}
-(int) getHiddenStartPos {
return _startPos;
}
#end
#implementation myClass
-(void) setStartPos: (int) Pos {
[self setHiddenStartPos: Pos];
}
-(int) getStartPos {
return [self getHiddenStartPos]; //this is to see if I can get the value from the hidden methods through the non-hidden ones
}
#end
that's all fine, and testing it in main() I can see that the methods with "hidden" in their name are in fact inaccessible, and therefore act as if they are private.
Then I tried to add this to the header file:
#property (assign, readwrite, setter = setHiddenStartPos:, getter = getHiddenStartPos) int
to see if I could access the hidden methods through the property
but when I did that, the hidden methods became accessible in main() and the whole plan with making the methods only accessible through the property went down the drain
So I ask you, is there a way to make methods inaccessible to anything BUT the property and/or the object itself?
Edit: I realize that getters don't usually have get in the name, so please stop commenting on it?
also to emphasise what I meant:
I wanted to make properties like in c#, where the content of the setters and getters are private to the property itself
public int exampleProperty
{
set{...}
get{...}
}
it doesn't use methods as getters and setters, and therefore the code in the setters and getters are accessible to only the property, JUST like the code within a method is local to the method itself
Add a class continuation in your .m file. i.e.:
#interface myClass ()
#property (assign, readwrite, setter = setHiddenStartPos:, getter = getHiddenStartPos) int hiddenStartPos;
#end
#implimentation myClass
#synthesize hiddenStartPos = _hiddenStartPos;
...
#end
Have a look at: What is an Objective-C "class continuation"?
PS: Your getters should just be hiddenStartPos rather than getHiddenStartPos...
It seems to me that the your confusion comes from misunderstanding exactly what an #property declaration is. It is essentially a declaration that setter and getter methods exist.
So, this
#property int hiddenStartPos;
is the same as this
- (int)hiddenStartPos;
- (void)setHiddenStartPos;
So, the implementation of these two methods is the implementation of the property. By decaring the property in the .h file, you're advertising to anyone who imports the .h that the class in question implements these two methods (the getter and the setter, respectively).
I also want to reemphasize that getter methods should not be prefixed with "get" in Objective-C.
You're over-thinking what "private" means. In ObjC, "private" just means "not visible." It doesn't mean "not callable." The way you make a method private is to not put it in your .h file, which declares your public interface.
There is no way to control who passes a message. This is a key fact of ObjC and cannot (and should not) be changed. ObjC is a dynamic language. At runtime, I am free to generate selectors and call performSelector: on any object I want. Anything that stopped that would either (a) introduce significant performance penalties, or (b) break many very useful and common techniques in ObjC (probably both). ObjC is not Java or C#. It's not even C or C++. It's Smalltalk on top of C. It's a highly dynamic language and that has a lot of strengths. Unlearning other languages is the first step towards becoming a good Cocoa developer.
It would be nice to have a compiler-checked #private for methods (of which properties are just a special case), and it would especially be awesome to have a compiler-checked #protected for methods (these exist for ivars). These would make it slightly simpler to avoid some kinds of mistakes. But that's the only way you should be thinking about this. The goal is not to protect one part of the code from another part of the code. The other code is not the enemy. It's all written by people who want the program to work. The goal is to avoid mistakes. Correct naming, consistency, and the absolute elimination of warnings is how you achieve that in ObjC.
So yes, I'd love to be able to put #protected in front of my #property declarations occasionally. Today you can't, and there is no real equivalent (I sometimes use a +Protected category in a separate header, but it's generally more trouble than its worth). But that said, having it wouldn't change very much, and I only find a case where I would even use this a few times a year. I can't think of single case where #private for a method would have been really useful, though.

use of #property and #synthesise?

I was wondering what the point of #property and #synthesise were. At the moment I use the following to declare something:
//Class.m
#import "Class.h"
CCNode *node;
#implementation
//init, etc..
But I have seen others use:
#property (nonatomic, etc..) CCNode* node;
#synthesise (nonatomic, etc..) node;
//I am not too sure on how this type of declaration works, please correct me on how it's done.
They both seem to work in the same way, what are the advantages of the #property and #synthesise way? Do they do different things, if so, what?
#property and #synthesize are two objective C keyword that allow you to easily create your properties and therefore avoid to write by hand getters and setters methods of the property.
The #property define the property itself, should be placed in the header file and can get some attributes (as for example : strong, nonatomic, retain assign, copy), the #synthesize should be placed into the implementation file and tell the compiler to generate the body of getter and setter method.
These two keyword are extremely useful when coupled with the right use of their attributes, because they take care of the generation of the property code and most of all they take care of the memory management of the property.
#property - create the declaration of your getter and setter.
#synthesize - provide the definition of getter and setter based upon the parameters which are passed inside property.
Check this out, there are a lot more details about the same present there - https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
on using #property the compiler will take care of declaring getter and setter methods based on readonly and readwrite
readonly -> getterMethod
readwrite -> both setter and getter method
on using #synthesize the compiler will take care of defining getter and setter methods
If you have an instance variable (ivar) in your class, you can't access it from other classes usually. So you have to make public accessor methods (getters and setters). They look something like this:
Setter:
- (void)setMyVariable:(SomeClass *)newValue {
if (newValue != myVariable) {
[myVariable release];
myVariable = [newValue retain];
}
}
Getter:
- (SomeClass *)myVariable {
return myVariable;
}
This was the way you had to do it before Objective-C 2.0. Now you can use #property and #synthesize to speed this up. It's basically just a shortcut.
In the header you use #property to define what kind of setters you want. Should the setter retain the passed value (like in my example) or copy or just assign?
And in the implementation you just write #synthesize to make the compiler include the automatically created getters and setters at that position. Usually at the top of your implementation.
My feeling is that all iVars should have an associated underscore synthesised property (using an _iVar prevents accidental direct access), and all access to the iVars, apart from init and dealloc methods, should via the property.
IMHO the big win is memory management - it's safer and much easier as there is no need to remember which iVars have been retained.
And think of how much work is required to code an accessor - 4 lines for getter and 2 for a setter.
At some point in the future #synthesize is likely to be optional, so all you'll need is the #property.

How to provide additional custom implementation of accessor methods when using #synthesize?

I want to fire some code when a property is accessed and changed. I use #property and #synthesize in my code for my ivars. The properties are retained, so I'd like to keep that memory management stuff automatically generated by #synthesize.
However, I assume that #synthesize tells the compiler to generate the accessor methods code right where #synthesize is, so most of the cases at the top of the code, right?
And when I have a property foo, I get -setFoo and -foo methods. Could I then just make a method like this, to execute some more custom code when a property is changed?
-(void)setFoo {
// custom stuff
}
Now that's a problem. How to execute the first one? I wouldn't love to have a different name here. Is there maybe a way to let the #synthesize directive create other names for getter and setter methods, which I then call easily? And I would still be able to use the dot syntax then to access them?
You can use #property and #synthesize just like you normally would, but provide a custom setter or getter (or both) and those will be used instead. Typically I will do something like this:
// Override the setter
- (void)setName:(NSString *)aName
{
if (name == aName)
return;
[name release];
name = [aName retain];
//custom code here
}
When I use the set property, it will invoke my custom method. However, the get will still be synthesized.
If you provide an implemnetation for the setters or getters it will use that instead of the generated implementation. Its not hard to implement the "retaining" aspect of the getters and setters that are generated for you by the compiler when u synthesize, so you can just write your own getters and setters i would say and go with that.
One wacky solution is to create an abstract super class that does gives you the normal property synthesis.
Then create a concrete subclass that you will actually use, and that simply implements and override method (same signature) and calls super to do the actual setting.
This allows you to do whatever you want to do before or after the call to super's implementation.
Example:
#interface ALTOClassA : NSObject
#property NSString *catName;
#end
Nothing else needed in the .m beyond the stubbed file for this test.
Create the subclass, nothing needed specially in the #interface
#import "ALTOClassA.h"
#interface ALTOClassAJunior : ALTOClassA
#end
In the #implementation we do our override.
#import "ALTOClassAJunior.h"
#implementation ALTOClassAJunior
- (void)setCatName:(NSString*)aCatName {
NSLog(#"%#",NSStringFromSelector(_cmd));
[super setCatName:aCatName];
NSLog(#"after super: self.catName %#", self.catName);
}
#end
In use:
ALTOClassAJunior *aCAJ = [ALTOClassAJunior new];
NSLog(#"aCAS.catName %#", aCAJ.catName);
NSLog(#"set it to George.");
[aCAJ setCatName:#"George"];
NSLog(#"aCAS.catName %#", aCAJ.catName);
This allows you to leverage the autogenerated code, and still do stuff you want to do with your class. Abstract Super Class is often a useful solution for many things.
Yes, in your #property declaration, you can specify the getter and setter methods.
#property (readwrite,getter=privateGetFoo,setter=privateSetFoo:) NSObject * foo;
In your foo and setFoo: methods, call [self privateGetFoo] or [self privateSetFoo:f] then your custom code.
The object can also set an observer on itself with addObserver:forKeyPath:options:context:.
That said, I don't think either of these are very clean ways to do things. Better to write your own getter/setter as others have suggested.