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.)
Related
I have a class which has 5 properties which should not be modified by other classes (and subclasses with more of these). I want to make these properties readonly, but I would then have to write a monster -init... to supply values for all these properties.
Of course I could edit the ivars directly, but I don't want to fetch the values in the constructor, as I want to pull those values from the StackExchange API. Separating this into a factory class seems more appropriate here.
tl;dr: How to initialise readonly properties from a factory class without an abnormally long constructor?
It might be a design error. If so, please add an answer suggesting a different approach, because the point of this project is to learn about design.
If you want the factory class to have the ability to update generally readonly properties and you want to avoid exceptionally long init method with a dizzying array of parameters, the typical solution in Objective-C is inelegant, but consists of defining a .h class category (used only by the factory class) that exposes the otherwise private or readonly properties.
For example, consider your CustomObject defined like so:
// CustomObject.h
#import <Foundation/Foundation.h>
#interface CustomObject : NSObject
#property (nonatomic, readonly) NSUInteger identifier; // public interface is readonly
#end
The implementation would define a private class extension that makes it clear that it's really readwrite even thought the public interface is readonly:
// CustomObject.m
#import "CustomObject.h"
#interface CustomObject ()
#property (nonatomic, readwrite) NSUInteger identifier; // it's really readwrite and setter will be synthesized, too
#end
#implementation CustomObject
#end
You can then define category header, that will be used only by the factory class, that exposes the fact that the CustomObject property of identifier is readwrite:
// CustomObject+Factory.h
#import "CustomObject.h"
#interface CustomObject (Factory)
#property (nonatomic, readwrite) NSUInteger identifier;
#end
If you look at <UIKit/UIGestureRecognizerSubclass.h> you'll see a slightly different application of the same concept, in which they expose the notion that the state property is readwrite (whereas it otherwise appears to be readonly).
Normally, in that case, you would make them publicly readonly, but privately readwrite. You can do so by adding a class extension (nameless category at the top of your .m), where you redefine the property without the readonly classifier.
// MyClass.h
#interface MyClass
#property (nonatomic, readonly) NSInteger myProperty;
#end
// MyClass.m
#interface MyClass () // Note the ()
#property (nonatomic) NSInteger myProperty;
#end
Now, within your class you can write the property, but outsiders can only read it.
You can't have it both ways. To my knowledge, Objective-C does not have the concept of "friend" members, meaning members that are accessible to only certain classes. Therefore, your only choice is to create public read-only properties and set their values in the constructor. In essence, your class could be treated as immutable. Yes, the init method may get quite long, but blame that on Objective-C's verbosity for such things. It's still the correct design choice.
MyClass.h:
#interface MyClass : NSObject
#property (copy, readonly, nonatomic) NSString *value1;
#property (assign, readonly, nonatomic) NSInteger value2;
- (instancetype)initWithValue1:(NSString *)value1 value2:(NSInteger)value2;
#end
MyClass.m:
#implementation MyClass
- (instancetype)initWithValue1:(NSString *)value1 value2:(NSInteger)value2
{
self = [super init];
if (self)
{
_value1 = value1;
_value2 = value2;
}
return self;
}
#end
You may also want to consider using JetBrains' AppCode product, as it has refactoring tools that might help with creating init methods from properties (although I haven't done this myself).
You can make constructor with only one parameter (NSArray or NSDictionary, dictionary seems less preferred because of keys), and send all 5 properties values in defined order or with defined key (as you will initialize you objects only in factory you will need to carry about correct order only in one place). In this case, if number of properties grows will be no needs to rename constructor method and adding more and more parameter names.
Also, you can simply use setVale:forKey: method, whith no matter is property readonly.
There are two approaches, and you may be trying to force these two into one model (physical object):
1) If the base provides the storage (e.g. ivars), then the values belong in the initializer. Simple as that - do guarantee the values are readonly for your sanity.
2) Lazy initialization. Your post suggests this is ideal for execution. The answer to this is that storage is an implementation detail. Let your ivars be stored by the class, and written when loaded.
Really, you want to reuse your programs and avoid making monstrous hierarchies and relying on inheritance for reuse. Consider how your 5 properties may be abstracted -- this would be by one or multiple helper classes (e.g. which provide these properties) which adopt a common protocol of the properties they vend. In this way, you may load lazily, copy, use initialization, or a number of other approaches.
Then your "subclasses" would just have a property which contains one of these objects which represents the "Base 5 Properties". Subclasses would not need 5 parameters. They would only need an id<MonBase5Properties> parameter. Again, an implementation (which adopts the protocol) may store the properties, and another may load them on demand. Either way, it's a convenient way to pack up a common set of data or interface into a type (class or protocol).
I'm working on building an iOS 6 app.
I have a class TDBeam which inherits from superclass TDWeapon.
The superclass TDWeapon declares a #property in the TDWeapon.h file:
#interface TDWeapon : UIView
#property (nonatomic) int damage;
#end
I do not explicitly #synthesize the property, as I'm letting Xcode automatically do so.
In the subclass TDBeam I override the getter in the TDBeam.m file:
#import "TDBeam.h"
#implementation TDBeam
- (int)damage {
return _damage;
}
#end
Xcode auto-completes the getter method name, as expected. But when I attempt to reference the _damage instance variable (inherited from the superclass), I get a compiler error:
Use of undeclared identifier '_damage'
What am I doing wrong here? I've tried explicitly adding #synthesize, and changing the name of the _damage ivar, but the compiler doesn't "see" it or any other ivars from the superclass. I thought ivars were visible and accessible from subclasses?
Synthesized ivars are not visible to subclasses, whether they are explicitly or automatically created: What is the visibility of #synthesized instance variables? Since they are effectively declared in the implementation file, their declaration isn't included in the "translation unit" that includes the subclass.
If you really want to access that ivar directly, you'll have to explicitly declare it (in its default "protected" form) somewhere that the subclass can see it, such as a class extension of the superclass in a private header.
There are a lot of posts on this topic on Stack Overflow, none of which offer simple concrete advice, but this topic sums it up most succinctly, and Josh's answer is the best in any.
What he kinda stops short of saying outright, is, if this is the kind of thing you want to do, don't use #property at all. Declare your regular protected variable in your base class as he says, and write you're own setters and getters if you need them. The ivar will be visible to any subclasses who can then write their own setters/getters.
At least that's where i've landed on the issue, although I'd a total newb to subclassing.
The idea of creating private headers to host your anonymous category and re-#sythesizing your ivars in your subclass just seems wrong on so many levels. I'm also sure I've probably missed some fundamental point somewhere.
Edit
Okay after some lost sleep, and inspired by Stanford's 2013 iTunes U course, here I believe is an example solution to this problem.
MYFoo.h
#import <Foundation/Foundation.h>
#interface MYFoo : NSObject
// Optional, depending on your class
#property (strong, nonatomic, readonly) NSString * myProperty;
- (NSString *)makeValueForNewMyProperty; //override this in your subclass
#end
MYFoo.m
#import "MYFoo.h"
#interface MYFoo ()
#property (strong, nonatomic, readwrite) NSString * myProperty;
#end
#implementation MYFoo
// Base class getter, generic
- (NSDateComponents *)myProperty {
if (!_myProperty) {
_myProperty = [self makeValueForNewMyProperty];
}
return _myProperty;
}
// Replace this method in your subclass with your logic on how to create a new myProperty
- (NSString *)makeValueForNewMyProperty {
// If this is an abstract base class, we'd return nil and/or throw an exception
NSString * newMyProperty = [[NSString alloc]init];
// Do stuff to make the property the way you need it...
return newMyProperty;
}
#end
Then you just replace makeValueForNewMyProperty in your subclass with whatever custom logic you need. Your property is 'protected' in the base class but you have control over how it is created, which is basically what you are trying to achieve in most cases.
If your makeValueForNewMyProperty method requires access to other ivars of the base class, they will, at the very least, have to be be public readonly properties (or just naked ivars).
Not exactly 'over-ridding a getter' but it achieves the same sort of thing, with a little thought. My apologies if, in trying to make the example generic, some elegance and clarity has been lost.
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).
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.
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.