In Objective-C, why does the variable's type has to be repeated for #property? - objective-c

For Objective-C, in the following header file:
#interface Peg : NSObject {
char color;
}
#property char color;
I wonder if the member variable is already said to be a char type, then why does the #property has to repeat it? (or else it won't compile). Couldn't the compiler tell that it is char? It couldn't be anything else, could it?

That is because generaly properties don't have to be related to any declared instance variable of your class. You may have a property and not include a variable into your class header. That's why you have to declare it's type.
Using properties instead of variables makes your headers clean, hiding the implementation.
So, you can just declare a property and then #synthesize it
#interface Peg : NSObject
#property char color;
#implementation Peg
#synthesize color;
#end

Actually, it's no longer needed, at least when compiling for x64 with clang. If you omit instance variable, #synthesize will create one for you.

Just use The following
#interface Peg : NSObject {}
#property char color;

Related

Need help trying to use #property in Objective-C

New to Objective-C (and programming for that matter), so please don't be too harsh if this question is very basic.
Apart from my main.m class, I have a Student.h and Student.m class, which I created. I am trying to avoid using many getters and setters for future projects, and if I'm correct, #property can help me with that. My basic code that works is this:
Student.h:
#import <Foundation/Foundation.h>
#interface Student : NSObject{
NSString *name;
int age;
}
//setters
- (void)setName:(NSString*)fName;
- (void)setAge:(int)newAge;
//getters
- (NSString*)getName;
- (int)getAge;
#end
Student.m:
#import "Student.h"
#implementation Student
- (void)setName:(NSString*)fName {
name = fName;
}
- (void)setAge:(int)newAge {
age = newAge;
}
- (NSString*)getName {
return name;
}
- (int)getAge {
return age;
}
#end
Can I use #property to have something like this, which would avoid using getter and setter methods? Or do I understand it all wrong?
#import <Foundation/Foundation.h>
#interface Student : NSObject{
}
#property int age;
#property NSString *name;
#end
Few things:
In Objective C you don't use get prefix for getters. You should use either plain name or with 'is' prefix for boolean properties. (Objective C conventions reference)
You really won't avoid using getters and setters. #property notation just defines them for you (maybe with some additional behaviors like copying the value instead of assigning it). It's just the matter of . notation. Underneath it's using getter/setter methods. Here you have a bit more on properties (Objetive C properties reference).
You should define your NSString property as (copy). It's much better to have as if you change it somewhere else it will affect this object (and probably you want to avoid that).
Are you coming from Java perhaps?
Yes, Objective-C used to require getters and setters to be written out laboriously by hand. Nowadays if you use #property and don't go out of your way to do anything else then a suitable instance variable and an appropriate getter and setter will be generate for you.
So the following is a complete class with usable properties, accessible either via traditional setName:/name-style setters and getters or via the dot notation (which calls the setters and getters despite looking like a C struct access:
#interface Student : NSObject
#property int age;
#property NSString *name;
#end
/* ... */
#implementation Student
#end
Also as a general encapsulation / data-hiding comment, notice that Objective-C has long ago been modified so that instance variables can be declared in the [unpublished] #implementation rather than the [published] #interface. On a technical level it was all to do with the ABI and the fragile base class problem, neither of which haunts the modern runtime.

Modern Objective-C and #synthesize

I'm trying convert my code to Modern Objective-C style. How i read here http://www.techotopia.com/index.php/The_Basics_of_Modern_Objective-C": "In the case of Modern Objective-C, however, the synthesis takes place by default, making the use of #synthesize declarations unnecessary. When using default property synthesize, instance variable properties are accessible from within code using the property name prefixed with an underscore."
However, I have:
Relationship.h
#interface Relationship : NSObject <NSCoding>
//...
#property(nonatomic, weak) Person* first;
//...
#end`
OtherRelationship.h
#import "Relationship.h"
#interface OtherRelationship : Relationship
#end
OtherRelationship.m
#import "OtherRelationship.h"
#implementation OtherRelationship
#synthesize first = _first;
- (void)foo
{
NSLog(#"%#", _first);
}
and it's working. But when i delete
#synthesize first = _first;
i get "Use of undeclared identifier '_first'" error. Does inheritanced variables doesn't work with autosynthesize or should i looking for problem elsewhere?
The backing ivar in the superclass is #private to the subclass. That is, the subclass may call self.first, but not _first. If you want to #synthesize again, use a different name because you can't refer to _first. For example, replace with #synthesize first = _ffirst; or just drop the #synthesize.

declaring class in controller

I'm reading an Objective-C Fundamentals book that's taking me through the construction of a basic app. However, it doesn't always show us what to do. At one point, it says
open RootViewController.h and remove the existing definitions for the PropertyType enumeration and RentalProperty structure. Replace them with the CTRentalProperty class.
Ok, it's easy to find the enumeration and structure it referred to...
typedef enum PropertyType {
Unit,
TownHouse,
Mansion
} PropertyType;
typedef struct {
NSString *address;
PropertyType type;
double weeklyRentalPrice;
} RentalProperty;
but what exactly does it mean (what is the actual code) when it says
Replace them with the CTRentalProperty class
Do I just write
CTRentalProperty;
Probably not. Can you help me understand what the author's talking about. We've made CTRentalProperty.h and CTRentalProperty.m classes/files, but I'm not sure if I'm supposed to copy code from them into the controller.
Probably it means to put
#interface CTRentalProperty : NSObject
{
NSString *address;
PropertyType type;
double weeklyRentalPrice;
}
#end
into CTRentalProperty.h in place of the struct definition. You'll then need to put
#implementation CTRentalProperty
#end
into CTRentalProperty.m.
Not sure about the enum, but the author probably means something like this:
#interface CTRentalProperty : NSObject
#property(nonatomic, strong) NSString *address;
#property(nonatomic, assign) PropertyType type;
#property(nonatomic, assign) double weeklyRentalPrice;
#end
Answering my own question after discovering author provides source code. Although it doesn't seem to make sense given the instructions he provided in the book. Here's what the controller's supposed to look like
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController {
NSDictionary *cityMappings;
NSArray *properties;
}
#end

Are curly braces required in #interface declarations in Objective-c?

The following code compiles:
#interface MyClass : ParentClass // missing {
// missing }
#property (nonatomic, copy) NSString *myString;
#end
I'm wondering if the curly braces in #interface declarations are actually necessary.
No, the { } section isn’t necessary; your code will compile fine without it. It’s the area where you declare instance variables, and if you’re not doing that, you’re free to leave it out. You don’t even actually need to declare ivars for your properties—the compiler’s smart enough to add them where they’re needed.
The compiler is clever enough to add your #property delarations to the class.
The only use for those brackets is when you want to make a variable private, protected or specifically public.
Example:
#interface Example: NSObject {
#public
int publicVar;
#private
int privateVar;
int privateVar2;
#protected
int protectedVar;
}
#end

Do I need to declare a property in the instance variables section, too? What do I gain?

I read some tutorials here about properties ,but i still have some doubts to clarify, is there a difference between
#interface MyClass : NSObject {
}
#property(nonatomic,retain) NSString *temp;
#end
AND
#interface MyClass : NSObject {
NSString *temp;
}
#property(nonatomic,retain) NSString *temp;
#end
The difference is that in the first version, the compiler will automatically create an instance variable (IIRC, it will be named _temp but I don't know for sure). This is only supported on iOS and Mac 64 bit.
In the second example, you provide the variable.
There's actually a way to tell the compiler which variable to use for the property, which I use a lot:
#interface MyClass : NSObject {
NSString *temp_;
}
#property(nonatomic,retain) NSString *temp;
#end
#implementation MyClass
#synthesize temp = temp_;
#end
This way the variable and the property have different names and you can't confuse them (e.g. by forgetting to prefix self.).
Minor side-note: it's often desirable to use copy instead of retain for NSString *, since you might assign an NSMutableString * to the property. Now if you would change that mutable string unexpected things might happen.
Does the first one even work? If there is no instance variable its a bit hard to have a property to access it.
#properties are meant for you, so you can be lazy, they write the following 2 methods for you ( if not set to readonly ):
- (void)setYourVariable:(id)new;
- (id)yourVariable;
it also allows you to use "someClass.itsVariable;" instead of "[someClass itsVariable];"
Another thing, when you create your header files make sure that the biggest variables ( like pointers ) are on the top and the smallest on the bottom, this saves ram.
thus:
NSObject *someObject;
NSObject *someOtherObject;
int anInt;
short aShort;
BOOL fakeBool;
instead of:
BOOL fakeBool;
NSObject *someObject;
short aShort;
NSObject *someOtherObject;
int anInt;
This has to do with the compiler, you can check this by using sizeof()
In the modern runtime (Objective-C 2.0) it is the same because the compiler will generate the variable for you. See Question about #synthesize
Quoting The Objective-C Programming Language > Declared Properties > Property Implementation Directives:
There are differences in the behavior of accessor synthesis that
depend on the runtime:
For the legacy runtimes, instance variables must already be declared in the #interface block of the current class. If an instance
variable of the same name as the property exists, and if its type is
compatible with the property’s type, it is used—otherwise, you get a
compiler error.
For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is
used.
The practical difference that I've found is that the debugger doesn't appear to show you the value of properties, just instance variables.
Therefore, your first example, which (assuming you use the #synthesize directive to create your getter/setter) automatically creates the ivar, will not have a value that you can easily retrieve during debug. You'll end up having to send a lot of NSLog messages, rather than just looking at the values while stepping through your code.
As an aside, which seems to relate to this topic, I typically prepend my ivars with "iv" and change my color settings in XCode preferences so that I'm never unsure whether I'm accessing a property or an ivar.
Example
#interface MyClass : NSObject {
NSString *ivName;
NSString *ivTitle;
}
#property (nonatomic, copy) NSString *Name;
#property (nonatomic, copy) NSString *Title;
#end
Now, this then requires a small trick (to tie the two together) when synthesizing the properties, which I show below:
#implementation MyClass
#synthesize Name = ivName;
#synthesize Title = ivTitle;
This way, it's always very easy for me to know exactly what's going on at a glance. Yes, context can also tell you whether you're accessing an ivar/property, but why not make it easier?