Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (24.65 MB, 900 trang )
@interface Person : NSObject
@property (nonatomic, strong) NSString *firstName;
@end
Now try to compile your program by pressing Command+Shift+R. Note that the LLVM
Compiler will give you two warnings:
warning: property 'firstName' requires method 'firstName' to be defined - use @synthesize, @dynamic or p
warning: property 'firstName' requires method 'setFirstName:' to be defined - use @synthesize, @dynamic
You will learn all about new Automatic Reference Counting keywords
such as strong, in Recipe 1.16.
It's obvious that the property has been created, but the compiler doesn't know what to
do in case somebody tries to read this property or assign a value it. For this reason, we
have to write a setter and a getter method. The compiler is clearly telling us that the
setter method should be called setFirstName: and the getter method should be called
firstName. Fortunately, we don't have to write these two methods for properties manually. We can use the @synthesize keyword in the .m file to let the compiler generate
the setter and the getter methods for our properties automatically:
#import "Person.h"
@implementation Person
@synthesize firstName;
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
}
return self;
@end
Now we can go ahead and use our Person class. Here is an example:
#import "SomeOtherClass.h"
#import "Person.h"
@implementation SomeOtherClass
- (void) makeNewPerson{
Person *newPerson = [[Person alloc] init];
newPerson.firstName = @"Andrew";
52 | Chapter 1: The Basics
www.it-ebooks.info
NSLog(@"First name = %@", newPerson.firstName);
NSLog(@"First name = %@", [newPerson firstName]);
}
@end
The example code prints the first name of newPerson twice, first using its firstName
property and then by calling the firstName getter method on that object. Both will point
to the same method, which @synthesize created for us in the Person.m file.
In an older version of the Objective-C runtime, for @property to work,
we also had to define an instance variable. An instance variable is a variable whose memory management is done by the programmer herself.
Instance variables are also not exposed to classes outside the scope of
the class that defines them (that is, they are not exposed to any class
that simply imports the class with the instance variable). Instance variables are normally called ivars by professional Objective-C developers.
Ivars is pronounced like I-VAR with the VAR part pronounced like
WAR, with a V.
With the new runtime, we don't have to define ivars anymore. We simply define the property and the LLVM compiler defines the ivar for us.
If you are using the GCC compiler, which is rather unlikely, you will see
big differences from how the LLVM compiler treats ivars. For instance,
in GCC 4.2, an ivar is not accessible to any subclass of a class, whereas
if you are using LLVM Compiler, a subclass of a class can use its superclass's ivars. So make sure you are using Apple's latest compiler, which
is LLVM.
If you want to fiddle around with setter and getter methods, you are free to do so. Even
if you have used @synthesize to allow the compiler to generate the setter and getter
methods of a property for you, you can still go ahead and override those methods. For
instance, in this example, I change the setFirstName: setter method of the firstName
property of the Person:
#import "Person.h"
@implementation Person
@synthesize firstName;
- (void) setFirstName:(NSString *)paramFirstName{
firstName = [paramFirstName stringByAppendingString:@" Jr"];
}
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
1.15 Adding Properties to Classes | 53
www.it-ebooks.info
return self;
}
@end
I have overridden the setter method of my firstName property to add a " Jr" suffix to
any string that I am told to assign to the firstName property. So when the setter and
getters are invoked, as before:
Person *newPerson = [[Person alloc] init];
newPerson.firstName = @"Andrew";
NSLog(@"First name = %@", newPerson.firstName);
NSLog(@"First name = %@", [newPerson firstName]);
We will get the following printed out to the console window:
First name = Andrew Jr
First name = Andrew Jr
If you want to define a read-only property, all you have to do is to define your property
using the @readonly keyword, like so:
@property (nonatomic, strong, readonly) NSString *lastName;
If a property is read-only, the only way that property's value can change
is for the class that defines that property to use the ivar of that property
to change the property's value.
See Also
XXX
1.16 Moving from Manual Reference Counting to Automatic
Reference Counting
Problem
You want to learn about Automatic Reference Counting, Apple's new Compiler solution to solving the headache that programmers had to deal with when working with
objects and memory management in Objective-C.
Solution
Study the new storage attributes introduced with the latest LLVM compiler: strong,
weak, and unsafe_unretained.
54 | Chapter 1: The Basics
www.it-ebooks.info
Discussion
In the latest LLVM complier, to use Automatic Reference Counting (ARC), we will
need to deal with storage that is strong, weak, or unsafe and unretained. Any object
under ARC is managed with one of these storage attributes. Here is a short explanation
for each one:
strong
An object of this type is automatically retained at run-time and will be valid until
the end of its scope, where it will automatically be released. For those familiar with
Objective-C's traditional way of memory management, this keyword is similar to
the retain keyword.
weak
This is zeroing weak referencing. If a variable is defined with this keyword, when
the object to which this variable points gets deallocated, this value will get set to
nil. For instance, if you have a strong string property and a weak string property
and set the weak property's value to the strong property's value, when the strong
property gets deallocated, the weak property's value will get set to nil.
unsafe_unretained
This is simply pointing one variable to another. This will not retain the object into
the new variable, it will simply assign the objct to the variable.
By default, all local variables are strong variables. In contrast, properties must explicitly
specify their storage attribute. In other words, the compiler won't assume that all properties without a storage attribute are by default strong properties. So do make sure that
you specify the storage attributes for your properties. Let's have a look at an example
of the strong storage attribute. Let's assume we have two properties called string1 and
string2:
#import
@interface Moving_from_Manual_Reference_Counting_to_ARCAppDelegate
: UIResponder
@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, strong) NSString *string1;
@property (nonatomic, strong) NSString *string2;
@end
Now if we initialize the string1 property with the value String 1 and assign this property's value to the string2 property, we will see that with the strong storage attribute,
the string2 property will keep its value even after string1 is deallocated:
#import "Moving_from_Manual_Reference_Counting_to_ARCAppDelegate.h"
@implementation Moving_from_Manual_Reference_Counting_to_ARCAppDelegate
1.16 Moving from Manual Reference Counting to Automatic Reference Counting | 55
www.it-ebooks.info