In Objective-C, should a wrapper property be set to weak? By wrapper property I mean that the property is a wrapper of another property.
e.g.
- (Prop *)prop {
return self.obj.prop; //wrapper method for another property
}
#property (nonatomic, readonly, weak) Prop *prop; // weak or strong?
"correct" in this case is a matter of convention and preference as Objective-C properties do support this pattern. Accessing a property does call a method which is either generated, synthesized or manually coded.
I'll stay out of whether it's "correct" or not.
Since your property only returns the value of a different property, then you don't need to specify strong or weak as they are meaningless.
In the public header:
# myclass.h
#interface MyClass
#property (nonatomic, readonly) OtherClass *someProperty;
#end
In the implementation:
# myclass.m
#implementation MyClass
- (OtherClass *)someProperty
{
return self.someObject.otherProperty;
}
Using a property is not necessarily the best way to go. It shouldn't really be weak or strong as it will never be set. You are never going to create a readwrite counterpart and generate an instance variable / accessor methods.
So, it's better to represent this as a simple method in the header file. It's more accurate as a description of the interface offered.
Related
What is difference of these three cases (all of them are used like private fields):
1.
#interface APLParseOperation : NSOperation
#property (copy, readonly) NSData *earthquakeData;
#end
2.
#interface APLParseOperation () <NSXMLParserDelegate>
#property (nonatomic) APLEarthquake *currentEarthquakeObject;
#property (nonatomic) NSMutableArray *currentParseBatch;
#property (nonatomic) NSMutableString *currentParsedCharacterData;
#end
3.
#implementation APLParseOperation
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
It's a good practice or smthing else?
I'm going to go through each example you gave, and describe them. I was just having trouble with this yesterday so I feel your pain.
1.
#interface APLParseOperation : NSOperation
#property (copy, readonly) NSData *earthquakeData;
#end
By using the #property keyword, the compiler automatically synthesizes your accessor methods for you, and also a backing instance variable. However, because you are using the readonly property attribute, the compiler is only synthesizing a getter method for you.
2.
#interface APLParseOperation () <NSXMLParserDelegate>
#property (nonatomic) APLEarthquake *currentEarthquakeObject;
#property (nonatomic) NSMutableArray *currentParseBatch;
#property (nonatomic) NSMutableString *currentParsedCharacterData;
#end
This second example is very similar to the first. However, because none of them have the readonly property attribute, they will all have getters and setter methods synthesized for them, as well as the backing instance variable.
3.
#implementation APLParseOperation
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
For this last example, you are just declaring instance variables. These are also private to your implementation file, where as the other 2 examples had declarations being made in your classes interface file.
No setter or getter methods are being synthesized for you by the compiler. You are simply declaring some instance variables.
In terms of private and public, your first and second examples both provide declarations that will be visible to other classes, as long as they import the current class's header file. The first example however, only provides a way to "get" the property and read it, there is no setter method because you used the readonly property attribute. With the second example, outside classes will be able to access your getter and setter methods for your property, so they can read and write.
For the third example, these are just instance variables and they are private to your class's implementation file. Basically, no outside classes will even know that they exist.
This is not private. It is still readable by outside classes, though it can't be written.
Private properties. It can be useful if you want to write custom getters and setters. If you are not using ARC, it can be helpful for memory management.
Private members. This is my favorite. It's easy to read and easy to write.
defines a public property visible to all users of the APLParseOperation class.
defines properties through an extension, making them available only to the implementation methods.
defines instance variables which are implicitly private.
Number 1 is used when you want to make your properties public. Numbers 2 and 3 are for private properties and instance variables. You can also declare instance variables in class extensions, like this:
#interface APLParseOperation () <NSXMLParserDelegate>
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
#end
There is not much difference between that and the number 3. It is a good idea to pick one style, and stick to it in all your code.
Case 1. is not private. It's a public read-only property: Reading is public, writing is only possible only in the private scope via the underlying ivar (thanks for pointing it out #mah).
Case 2. (if in a .m file) is extending the class by adding 3 private properties and making the protocol conformance private too.
Case 3. is declaring 4 private instance variables that can be used in all the implementation scope.
Objective-C best practice for private properties is case 2., as case 1. is not private at all, just read-only, and case 3. uses instance variables (aka ivar) which is less conventional than properties. More on that here: Reason to use ivars vs properties in objective c
Hope this helps,
If im declaring a class with property for example:
#property float radius, diameter;
So any object that will be created in this class or inherits from it, will have its own instance of radius and diameter right?
And this is also mean that they have their own setter and getter too right?
What i'm trying to fully understand is how do I deal with variable access in 2 ways:
1.When I want to make sure the user is not messing with the original value.
2.When I want to limit the users for instance variables he can get access and ones that he can not.
tnx
As to the first part, yes, any subclass will inherit it's superclasses properties and methods as long as they are public. Just remember to synthesise them to get the getter and setter.
So, if you want to have a public property that can't be modified:
// This returns a copy - whatever the receiver does with it doesn't affect the original
#property (nonatomic, copy) BOOL someVariable;
// This declares the property as only having a getter - no setter
#property (nonatomic, readonly) NSArray *someArray;
Any properties declared in your header file are considered public, unless otherwise specified. If you want to have private properties, ivars or methods, declare them in your implementation file in the class continuation category:
// In your .m *above* the #implementation MyClass
#interface MyClass()
#property (nonatomic, strong) NSArray *myPrivateModel;
#end
Stamford do a great lecture series on iTunesU which I'd really recommend for learning objectiveC
Hope that helps
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.
What the difference between declaring an #property in .h or .m file
#property (nonatomic, readwrite, assign) BOOL notificationDidLaunch;
Is it to do with the scope of the variable?
Also in the .h file whats the difference between declaring a string with the brakets like so
#interface AppDelegate : NSObject < UIApplicationDelegate > {
NSString *hat;
}
and doing it outside of them like below
#property (nonatomic, strong) NSString *hat;
As Tiago says, putting an #property declaration inside a class extension in the .m (implementation) file, is a way to make the property private so only the class itself can access it. When declared in the .h (public interface file), it is visible to all code that imports that .h file. Keep in mind that #properties are really just a convenience for declaring and synthesizing accessor methods, and as with all methods in Objective-C, they're never truly private. The best you get is a compiler warning that no public interface declares the method in question if you try to use a non-public method in another class.
For the second part of your question, this declares an instance variable ("ivar") called myString:
#interface MyClass : NSObject
{
NSString *myString;
}
While this declares a property called myString:
#property NSString *myString;
The difference between an instance variable and an #property is more significant than just saying that an ivar is accessible only by your class's instances. Declaring an ivar adds a variable to a class's structure in memory. In contrast, #properties declare/define methods on a class. By default, these methods set/get the value of an associated, and similarly named ivar, but that's not a requirement, and it is perfectly acceptable and quite common to have methods for an #property that don't access an ivar directly. Say for example a class that has a firstName and lastName properties backed by _firstName and _lastName ivars, along with a third, fullName property that simply concatenates the value returned by the firstName and lastName getter methods together (and/or splits a two part name in its set method).
A summarized explanation
A #property inside the .m is private to the class and in the .h is public.
The difference between declaring inside brackets or without brackets is the meaning of the variable.
Inside the brackets you declare an instance variable (or ivar) that is meant to be acessible only by your classes' instances. A property (declared in the .h) is meant to be acessible by any class.
Properties
A #property essentially defines a set and a get that you can override. When you do:
AppDelegate myAppDelegate;
myAppDelegate.hat = #"A hat":
You are essencially doing:
[myAppDelegate setHat:#"A hat"]
And when you do
myAppDelegate.hat //so you can get the property's value
you are essencially doing
[myAppDelegate hat]
Overriding Sets and Gets
When you do #synthesize hat = _hat you are essentially creating a get and a set that has an instance variable _hat associated. This instance variable should only be accessed in your gets/sets and even inside your class you should use your sets/gets (using self.property)
You can override the set and get created by the #synthesize overriding the following methods:
- (void) setHat:(NSString*) aHat
- (NSString *) hat
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.