main.m檔案
#import <Foundation/Foundation.h>
#import "Student.h"
#import "GoodStudent.h"
// copy文法的目的:改變副本的時候,不會影響到源對象
#pragma mark 字元串的拷貝(深拷貝)
// 深拷貝:内容拷貝,會産生新的對象。新對象計數器置為1,源對象計數器不變。
void stringMutableCopy() {
// string:1
NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];
// 産生了一個新的對象,計數器為1。源對象的計數器不變。
// str:1
// string:1
NSMutableString *str = [string mutableCopy];
//NSLog(@"str:%zi", [str retainCount]);
//NSLog(@"string:%zi", [string retainCount]);
// str和string不是相同對象
// NSLog(@"%i", str == string);
[str appendString:@" abcd"];
NSLog(@"string:%@", string);
NSLog(@"str:%@", str);
// str:0
[str release];
// string:0
[string release];
}
#pragma mark 示範字元串的拷貝(淺拷貝)
// 隻有一種情況是淺拷貝:不可變對象調用copy方法時
// 淺拷貝:指針拷貝,不會産生新的對象。源對象計數器+1。
void stringCopy() {
NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];
NSLog(@"%zi", [string retainCount]);
// copy産生的是不可變副本,由于源對象本身就不可變,是以為了性能着想,copy會直接傳回源對象本身
// 源對象計數器會+1
// 在淺拷貝情況下,copy其實就相當于retain
NSString *str = [string copy];
NSLog(@"%zi", [string retainCount]);
// NSLog(@"%i", str == string);
[str release];
[string release];
}
#pragma mark 可變字元串的copy(深拷貝)
void mutableStringCopy() {
NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];
// 會産生一個新對象,str計數器為1
NSString *str = [string copy];
[str release];
}
#pragma mark 可變字元串的MutableCopy(深拷貝)
void mutableStringMutableCopy() {
NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];
// 會産生一個新對象,str計數器為1
NSMutableString *str = [string mutableCopy];
[str appendString:@"1234"];
NSLog(@"str:%@", str);
NSLog(@"string:%@", string);
[str release];
}
#pragma mark Student的name的copy
void studentNameCopy() {
Student *stu = [[[Student alloc] init] autorelease];
NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];
stu.name = string;
[string appendString:@"abcd"];
NSLog(@"name=%@", stu.name);
NSLog(@"string=%@", string);
}
#pragma mark Student的copy
void studentCopy() {
Student *stu1 = [Student studentWithName:@"stu1"];
Student *stu2 = [stu1 copy];
stu2.name = @"stu2";
NSLog(@"stu1:%@", stu1);
NSLog(@"stu2:%@", stu2);
[stu2 release];
}
void goodStudentCopy() {
GoodStudent *stu1 = [GoodStudent goodStudentWithAge:10 name:@"good1"];
GoodStudent *stu2 = [stu1 copy];
stu2.name = @"good2";
stu2.age = 11;
NSLog(@"stu1:%@", stu1);
NSLog(@"stu2:%@", stu2);
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
goodStudentCopy();
}
return 0;
}
Student.h檔案
#import <Foundation/Foundation.h>
@interface Student : NSObject <NSCopying>
// copy代表set方法會release舊對象、copy新對象
// 修改外面的變量,并不會影響到内部的成員變量
// 建議:NSString一般用copy政策,其他對象一般用retain
@property (nonatomic, copy) NSString *name;
+ (id)studentWithName:(NSString *)name;
@end
Student.m檔案
#import "Student.h"
@implementation Student
+ (id)studentWithName:(NSString *)name {
// 這裡最好寫[self class]
Student *stu = [[[[self class] alloc] init] autorelease];
stu.name = name;
return stu;
}
- (void)dealloc {
[_name release];
[super dealloc];
}
#pragma mark description方法内部不能列印self,不然會造成死循環
- (NSString *)description {
return [NSString stringWithFormat:@"[name=%@]", _name];
}
#pragma mark copying協定的方法
// 這裡建立的副本對象不要求釋放
- (id)copyWithZone:(NSZone *)zone {
Student *copy = [[[self class] allocWithZone:zone] init];
// 拷貝名字給副本對象
copy.name = self.name;
return copy;
}
@end
GoodStudent.h
#import "Student.h"
@interface GoodStudent : Student
@property (nonatomic, assign) int age;
+ (id)goodStudentWithAge:(int)age name:(NSString *)name;
@end
GoodStudent.m
#import "GoodStudent.h"
@implementation GoodStudent
+ (id)goodStudentWithAge:(int)age name:(NSString *)name {
GoodStudent *good = [GoodStudent studentWithName:name];
good.age = age;
return good;
}
- (NSString *)description {
return [NSString stringWithFormat:@"[name=%@, age=%i]", self.name, _age];
}
- (id)copyWithZone:(NSZone *)zone {
// 一定要調用父類的方法
GoodStudent *copy = [super copyWithZone:zone];
copy.age = self.age;
return copy;
}
@end