Learn Objective C(4)Programming with Objective-C - Encapsulating Data and Custom

Learn Objective C(4)Programming with Objective-C - Encapsulating Data and Customizing Existing Classes

3. Encapsulating Data
3.1 Properties Encapsulate an Object's Values
Declare Public Properties for Exposed Data
@interface ZJUPerson : NSObject
@property NSString *firstName
@property NSString *lastName
@end

Use Accessor Methods to Get or Set Property Values
NSString *firstName = [somePerson firstName];
[somePerson setFirstName:@"Carl"];

By default, these accessor methods are synthesized automatically for you by the compiler.

@property (readonly) NSString *fullName;

The opposite of readonly is readwrite, it is default.

@property (getter=isFinished) BOOL finished;
@property (readonly, getter=isFinished) BOOL finished;

Dot Syntax Is a Concise Alternative to Accessor Method Calls
NSString *firstName = somePerson.firstName;
somePerson.firstName = @"Carl";

Getting a value using somePerson.firstName is the same as using [somePerson firstName]
Setting a value using somePerson.firstName = @"Carl" is the same as using [somePerson setFirstName: @"Carl"];

Most Properties Are Backed by Instance Variables
For a property called firstName, the synthesized instance variable will be called _firstName.
- (void) someMethod {
     NSString *myString = @"an string";
     _someString = myString;
}

_someString is an instance variable.

- (void) someMethod {
     NSString *myString = @"an string";
     self.someString = myString;
}

You can Customize Synthesized Instance Variable Names
@implementation YourClass
@synthesize propertyName = instanceVariableName;
…snip…
@end

The default is @synthesize firstName = firstName;

But we should always use
@synthesize firstName = _firstName;

You Can Define Instance Variables without Properties
It is best practice to use a property on an object any time you need to keep track of a value.
If we want to define our own instance variables without declaring a property, we can add them insides braces at the top of the class interface or implementation.

@interface SomeClass : NSObject {
     NSString *_myNonPropertyInstanceVariable;
}
@end

@implementation SomeClass {
     NSString *_anotherCustomInstanceVariable;
}
@end

Access Instance Variables Directly from Initializer Methods
Creating the initialize methods.
- (id)initWithFirstName:(NSString *)aFirstName lastName:(NSString *) aLastName;

- (id)initWithFirstName:(NSString *)aFirstName lastName:(NSString *) aLastName {
     self = [super init];
     if(self){
          _firstName = aFirstName;
          _lastName = aLastName;
     }
     return self;
}

The Designated Initializer is the Primary Initialization Method
We need to define one designated initializer among a lot of initialization methods.

You Can Implement Custom Accessor Methods
@property (readonly) NSString *fullName;
- (NSString *) fullName {
     return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

Properties Are Atomic by Default
@interface ZJUObject : NSObject
@property NSObject *firstObject;   //atomic by default
@property (atomic) NSObject *secondObject //
@end

From different threads, it is always fully retrieved by the getter method or fully set via the setter method.

atomic -- nonatomic
@interface ZJUObject : NSObject
@property (nonatomic) NSObject *oneobject;
@end

@implementation ZJUObject
- (NSObject *) oneobject {
     return _oneobject;
}
//setter will be synthesized automatically
@end

3.2 Manage the Object Graph through Ownership and Responsibility
In Objective-C, an object is kept alive as long as it has at least one strong reference to it from another object.
ZJUPerson Object
@property NSString *firstName;     -----strong -----> NSString Object @"Carl"
@property NSString *lastName;     ------strong -----> NSString Object @"Luo"

Avoid Strong Reference Cycles
If a group of objects is connected by a circle of strong relationships, they keep each other alive even if there are no strong references from outside the group.

A strong reference circle
NSTableView             -------> strong ------> Delegate Object
@property id delegate <------- strong -------- @property NSTableView *tableView;

NSTableView                        -------> weak ------> Delegate Object
@property (weak) id delegate <------- strong -------- @property NSTableView *tableView;

Use Strong and Weak Declarations to Manage Ownership
By default the references are strong
@property id delegate;

@property (weak) id delegate;

Local variables also maintain strong references to objects by default. If we don't want a variable to maintain a strong reference, we can declare __weak
NSObject *__weak weakVariable;

Use Unsafe Unretained References for Some Classes
@property (unsafe_unretatined) NSObject *unsafeProperty;
NSObject * __unsafe_unretained unsafeReference;

Copy Properties Maintain Their Own Copies
@interface ZJUBadgeView : NSView
@property NSString *firstName;
@property NSString *lastName;
@end

NSMutableString *nameString = [NSMutableString stringWithString:@"John"];
self.badgeView.firstName = nameString;

nameString appendString:@"ny";

The object ZJUBadgeView will change after the append action. So we need a copy of the value for the object in some circumstances.
@interface ZJUBadgeView : NSView
@property (copy) NSString *firstName;
@property (copy) NSString *lastName;
@end

alternatively

- (id) initWithSomeOriginalString:(NSString *) aString {
     self = [super init];
     if (self) {
          _instanceVariableForCopyProperty = [aString copy];
     }
     return self;
}

4. Customizing Existing Classes
4.1 Categories Add Methods to Existing Classes
@interface ClassName (CategoryName)

@end

At runtime, there is no difference between a method added by a category and one that is implemented by the original class.

Write the Category for ZJUPerson class like this.
#import "ZJUPerson.h"

@interface ZJUPerson (ZJUPersonNameDisplayAddtions)
     - (NSString *) lastNameFirstNameString;
@end

A category is usually declared in a separate header file and implemented in a separate source code file. For example
ZJUPerson+ZJUPersonNameDisplayAdditions.h

The category implementation is as follow:
#import "ZJUPerson+ZJUPersonNameDisplayAdditions.h"

@implementation ZJUPerson ( ZJUPersonNameDisplayAdditions)
     - (NSString *) lastNameFirstNameString {
          return [NSString stringWithFormat: @"%@, %@", self.lastName, self.firstName];
     }
@end

After implement the Category, we can use that method both in ZJUPerson class itself or the sub classes.

#import "ZJUPerson+ZJUPersonNameDisplayAdditions.h"

@implementation SomeObject
     - (void) someMethod {
          ZJUPerson *person = [[ZJUPerson alloc] initWithFirstName:@"Carl"
                                                                                  lastname:@"Luo"];
          NSLog(@"The people is %@", [person lastnameFirstNameString]);
     }
@end

We can provide different implementations for the category methods, depending on whether I am writing an app for OS X or iOS.

Avoid Category Method Name Clashes
We need to be very careful about method names, if the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime.

To solve the clashes, it is best practice to add a prefix to the method name.
+ (id) zju_sortDescriptorWithKey: (NSString *) key ascending: (BOOL) ascending;

4.2 Class Extensions Extend the Internal Implementation
A class extension bears some similarity to a category, but it can only be added to a class for which you have the source code at compile time.
There is no way to declare a class extension on a framework class.

@interface ClassName ()
@end

Since there is not name in the parentheses, class extensions are often referred to as anonymous categories. We can define the properties then.
@interface ZJUPerson ()
     @property NSObject *extraProperty;
@end

Use Class Extensions to Hide Private Information
…snip...

Consider Other Alternatives for Class Customization
…snip...


References:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html#//apple_ref/doc/uid/TP40011210-CH5-SW1




相关推荐