1. Trang chủ >
  2. Công Nghệ Thông Tin >
  3. Kỹ thuật lập trình >

15  Adding Properties to Classes

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



Xem Thêm
Tải bản đầy đủ (.pdf) (900 trang)

×