7.1 字元串(NSString與NSMutableString)
NSString:字元序列不可變的字元串
NSMutableString:字元序列可變的字元串
7.1.1 建立字元串
NSString功能:
- 建立字元串: 建立字元串既可以使用以init開頭的執行個體方法,也可以使用以string開 頭的類方法,當然也可以直接使用@“”的形式給出字元串直接量
- 讀取檔案或網絡URL來初始化字元串
- 将字元串内容寫入檔案或URL
- 擷取字元串長度,既可以擷取字元串内包括的字元個數,也可以擷取字元串包括的位元組個數
- 擷取字元串中的字元或位元組,既可擷取指定位置的字元,也可以擷取指定範圍的字元
- 擷取字元串對應的C風格字元串
- 連接配接字元串
- 分隔字元串
- 查找字元串内指定的字元和子串替換字元串
- 比較字元串
- 字元串大小比較
- 對字元串中的字元進行大小寫轉換
NSString的常見用法:
unichar data[6] = {97, 98, 99, 100, 101, 102};
//使用Unicode數值數組初始化字元串
NSString* str = [[NSString alloc] initWithCharacters:data length:6];
NSLog(@"%@", str);
char* cstr = "hello,ios";
//将C風格的字元串轉換為NSString對象
NSString* str2 = [NSString stringWithUTF8String:cstr];
NSLog(@"%@", str2);
//将字元串寫入指定檔案
[str2 writeToFile:@"myFile.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
//讀取檔案内容,用檔案内容初始化字元串
NSString* str3 = [NSString stringWithContentsOfFile:@"myFile.txt" encoding:NSUTF8StringEncoding error:nil];
NSLog(@"%@", str3);
輸出結果為:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLwkTMzEjNwcTM5ITNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
7.1.2 NSString的常用功能
NSString的常見用法:
NSString* str = @"hello";
NSString* book = @"《瘋狂iOS講義》";
//在str後面追加強定的字元串
//原來的字元串對象并不改變,隻是将新生成的字元串重新賦給str指針變量
str = [str stringByAppendingString:@",iOS!"];
NSLog(@"%@", str);
//擷取字元串對應的C風格字元串
const char* cstr = [str UTF8String];
NSLog(@"擷取的C字元串:%s", cstr);
//在str後面追加帶變量的字元串
//原來的字元串對象并不改變,隻是将新生成的字元串重新賦給str指針變量
str = [str stringByAppendingFormat:@"%@是一本非常不錯的圖書。", book];
NSLog(@"%@", str);
NSLog(@"str的字元個數為:%lu", [str length]);
NSLog(@"str按UTF-8字元集解碼後位元組數為:%lu", [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
//擷取str的前10個字元組成的字元串
NSString* s1 = [str substringToIndex:10];
NSLog(@"%@", s1);
//擷取str第5個字元之後的字元串
NSString* s2 = [str substringFromIndex:5];
NSLog(@"%@", s2);
//擷取str從第5個字元之後,數15個字元組成的字元串
NSString* s3 = [str substringWithRange:NSMakeRange(5, 15)];
NSLog(@"%@", s3);
//擷取iOS在str中出現的位置
NSRange pos = [str rangeOfString:@"iOS"];
NSLog(@"iOS在str中出現的開始位置:%ld,長度為:%ld", pos.location, pos.length);
//将str的所有字元大寫
str = [str uppercaseString];
NSLog(@"%@", str);
輸出結果為:
NSRange:
NSRange并不是一個類,它隻是一個結構體,它包括了location和length兩個unsigned int整型值,分别代表起始位置和長度。Objecetive-C還提供了NSMakeRange()函數來建立NSRange變量。
7.1.3 可變字元串(NSMutableString)
NSString類是不可變的類,即一旦NSSting對象被建立,包含在這個對象中的字元序列是不可改變的,直至這個對象被銷毀。
NSMutableString對象則代表一個字元串序列可變的字元串,而且NSMutableString是NSString的子類,是以NSString的方法,NSMutableString都可以直接使用,NSMutableString對象也可以直接當成NSString對象使用。
NSMutableString提供:appendFormat:、appendString:、deleteCharactersInRange:、insertString:atIndex:、replaceCharactersInRange:withString:、replaceOccurrencesOfString:options:range:、setString:方即可改變該字元串所包含的字元序列。
NSMutableString常見用法:
NSString* book =@"《瘋狂iOS講義》";
//建立一個NSMutableString對象
NSMutableString* str = [NSMutableString stringWithString:@"Hello"];
//追加強定的字元串
//字元串所包含的字元序列本身發生了改變,是以無須重新指派
[str appendString:@",iOS!"];
NSLog(@"%@", str);
//追加帶變量的字元串
//字元串所包含的字元序列本身發生了改變,是以無須重新指派
[str appendFormat:@"%@是一本非常不錯的圖書。", book];
NSLog(@"%@", str);
//在指定位置插入字元串
//字元串所包含的字元序列本身發生了改變,是以無須重新指派
[str insertString:@"fkit.org" atIndex:6];
NSLog(@"%@", str);
//删除從位置6開始之後的12個字元
[str deleteCharactersInRange:NSMakeRange(6, 12)];
NSLog(@"%@", str);
//将從位置6開始數9個字元将這9個字元替換成Objective-C
[str replaceCharactersInRange:NSMakeRange(6, 9) withString:@"Objective-C"];
NSLog(@"%@", str);
輸出結果為:
7.2 日期與時間
Objective-C為處理日期、時間提供了NSDate、NSCalendar對象,還提供了日期格式器來處理日期與字元串之間的轉換。
7.2.1 日期與時間(NSDate)
NSDate對象代表日期與時間,Objective-C中既提供了類方法來建立NSDate對象,也提供了大量以init開頭的方法來初始化NSDate對象。
NSDate常見方法的用途:
//擷取代表目前日期、時間的NSDate
NSDate* date1 = [NSDate date];
NSLog(@"%@", date1);
//擷取從目前時間開始,一天之後的日期
NSDate* date2 = [[NSDate alloc]
initWithTimeIntervalSinceNow:3600 * 24];
NSLog(@"%@", date2);
//擷取從目前時間開始,3天之前的日期
NSDate* date3 = [[NSDate alloc]
initWithTimeIntervalSinceNow:-3 * 3600 * 24];
NSLog(@"%@", date3);
//擷取從1970年1月1日開始,20年之後的日期
NSDate* date4 = [NSDate dateWithTimeIntervalSince1970:3600 * 24 * 366 * 20];
NSLog(@"%@", date4);
//擷取系統目前的Locale區域設定
NSLocale* cn = [NSLocale currentLocale];
//擷取NSDate在目前Locale下對應的字元串
NSLog(@"%@", [date1 descriptionWithLocale:cn]);
//擷取兩個日期之間較早的日期
NSDate* earlier = [date1 earlierDate:date2];
NSLog(@"較早的日期為:%@", earlier);
//擷取兩個日期之間較晚的日期
NSDate* later = [date1 laterDate:date2];
NSLog(@"較晚的日期為:%@", later);
//比較兩個日期,compare:方法傳回NSComparisonResult枚舉值,
//該枚舉類型包含NSOrderedAscending、NSOrderedSame和
//NSOrderedDescending三個值
//分别代表調用compare:的日期位于被比較日期之前、相同、之後
switch ([date1 compare:date3]) {
case NSOrderedAscending:
NSLog(@"date1位于date3之前");
break;
case NSOrderedSame:
NSLog(@"date1與date3日期相等");
break;
case NSOrderedDescending:
NSLog(@"date1位于date3之後");
break;
}
//擷取兩個時間之間的時間差
//date1 - date3
NSLog(@"date1與date3之間時間差%g秒"
, [date1 timeIntervalSinceDate:date3]);
//擷取指定時間與現在的時間差
//date2 - now
NSLog(@"date2與現在時間差%g秒"
, [date2 timeIntervalSinceNow]);
輸出結果為:
建立NSDate的類方法與執行個體方法基本相似,但NSDate的類方法以date開頭,而執行個體方法以init開頭。兩個NSDate之間可以比較大小,可以計算時間差,也可以把NSDate轉化為複合目前NSLocale的格式字元串。
NSLocale:
NSLocale代表一個語言、國際環境,比如大陸的簡體中文,就可以通過NSLocale對象來代表。同樣一個日期,在不同的語言、國家環境下,顯示出來的字元串是不同的。
7.2.2 日期格式器(NSDateFormatter)
NSDateFormatter代表一個日期格式器,它的功能就是完成NSDate與NSString之間的轉換。
使用NSDateFormatter完成NSDate與NSString之間的轉換的步驟如下:
1.建立一個NSDateFormatter對象。
2.調用NSDateFormatter的setDateStyle:、setTimeStyle:方法設定格式化日期、時間的風格。 其中,日期、時間風格支援如下幾個枚舉值。
NSDateFormatterNoStyle:不顯示日期、時間的風格。
NSDateFormatterShortStyle:顯示“短”的日期,時間風格
NSSDateFormatterMediumStyle:顯示“中等”的日期、時間風格。
NSSDateFormatterLongStyle:顯示“長”的日期、時間風格。
NSSDateFormatterFullStyle:顯示“完整”的日期、時間風格。
如果打算使用自己的格式模版,調用NSDateFormatter的setDateFormate:方法設定日期、時間模版即可。
3.如果需要将NSDate轉化為NSString,調用NSDateFormatter的stringFromDate:方法執行格式化即可;如果需要将NSString轉化為NSDate,調用NSDateFormatter的dateFromString:方法執行格式化即可。
簡單示範一下NSDateFormatter的功能和用法:
//需要被格式化的時間
//擷取從1970年1月1日開始,20年之後的日期
NSDate* dt = [NSDate dateWithTimeIntervalSince1970:
3600 * 24 * 366 * 20];
//建立兩個NSLocale,分别代表中國、美國
NSLocale* locales[] = {
[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]
,[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]
};
NSDateFormatter* df[8];
//為上面兩個NSLocale建立8個DateFormat對象
for (int i = 0; i < 2; i++) {
df[i * 4] = [[NSDateFormatter alloc] init];
//設定NSDateFormatter的日期、時間風格
[df[i * 4] setDateStyle:NSDateFormatterShortStyle];
[df[i * 4] setTimeStyle:NSDateFormatterShortStyle];
//設定NSDateFormatter的NSLocale
[df[i * 4] setLocale:locales[i]];
df[i * 4 + 1] = [[NSDateFormatter alloc] init];
//設定NSDateFormatter的日期、時間風格
[df[i * 4 + 1] setDateStyle:NSDateFormatterMediumStyle];
[df[i * 4 + 1] setTimeStyle:NSDateFormatterMediumStyle];
//設定NSDateFormatter的NSLocale
[df[i * 4 + 1] setLocale:locales[i]];
df[i * 4 + 2] = [[NSDateFormatter alloc] init];
//設定NSDateFormatter的日期、時間風格
[df[i * 4 + 2] setDateStyle:NSDateFormatterLongStyle];
[df[i * 4 + 2] setTimeStyle:NSDateFormatterLongStyle];
//設定NSDateFormatter的NSLocale
[df[i * 4 + 2] setLocale:locales[i]];
df[i * 4 + 3] = [[NSDateFormatter alloc] init];
//設定NSDateFormatter的日期、時間風格
[df[i * 4 + 3] setDateStyle:NSDateFormatterFullStyle];
[df[i * 4 + 3] setTimeStyle:NSDateFormatterFullStyle];
//設定NSDateFormatter的NSLocale
[df[i * 4 + 3] setLocale:locales[i]];
}
for (int i = 0; i < 2; i++) {
switch (i) {
case 0:
NSLog(@"-------中國日期格式-------");
break;
case 1:
NSLog(@"-------美國日期格式-------");
break;
}
NSLog(@"SHORT格式的日期格式:%@", [df[i * 4] stringFromDate:dt]);
NSLog(@"MEDIUM格式的日期格式:%@", [df[i * 4 + 1] stringFromDate:dt]);
NSLog(@"LONG格式的日期格式:%@", [df[i * 4 + 2] stringFromDate:dt]);
NSLog(@"FULL格式的日期格式:%@", [df[i * 4 + 3] stringFromDate:dt]);
}
NSDateFormatter* df2 = [[NSDateFormatter alloc] init];
//設定自定義的格式器模版
[df2 setDateFormat:@"公元yyyy年MM月dd日 HH時mm分"];
//執行格式化
NSLog(@"%@", [df2 stringFromDate:dt]);
NSString* dateStr = @"2013-03-02";
NSDateFormatter* df3 = [[NSDateFormatter alloc] init];
//根據日期字元串的格式設定格式模版
[df3 setDateFormat:@"yyyy-MM-dd"];
//将字元串轉換為NSDate對象
NSDate* date2 = [df3 dateFromString:dateStr];
NSLog(@"%@", date2);
輸出結果為:
其中,日期格式化字元串(dateFormat)涉及的格式占位符有
G // AD,即公元
yy // 顯示年份的末尾兩位
yyyy // 顯示完整年份
M // 1-9月顯示一位數字(1 ~ 9),10-12月顯示兩位數字(10 ~ 12)
MM // 顯示兩位數組月份(01 ~ 12)
MMM // 英文月份縮寫
MMMM // 英文月份全拼
d // 1-9日顯示一位數字(1~9),10-31日顯示兩位數字(10~31)
dd // 日期顯示兩位數字(01~31)
EEE // 星期幾縮寫(例如星期二,英文是Tue,中文是周二)
EEEE // 星期幾全拼(例如星期二,英文是Tuesday,中文是星期二)
aa // 加上這個,會顯示AM/PM
H // 24小時值,0-9小時顯示一位數字(0~9),10-12小時顯示兩位數字(10~12)
HH // 24小時制,顯示兩位數字
K // 12小時制,0-9小時顯示一位數字(0~9),10-12小時顯示兩位數字(10~12)
KK // 12小時制,顯示兩位數字
m // 0-9分顯示一位數字(0~9),10-59分顯示兩位數字(10~59)
mm // 顯示兩位數字(00~59)
s // 0-9分顯示一位數字(0~9),10-59分顯示兩位數字(10~59)
ss // 分鐘,顯示兩位數字(00~59)
S // 顯示毫秒
7.2.3 月曆(NSCalendar)與日期元件(NSDateComponents)
為了能分開處理NSDate對象所包含的各個字段的資料,Foundation架構提供了NSCalendar對象,該對象包含如下兩個常用方法:
- (NSDateComponents*)components:fromDate: :從NSDate提取年、月、日、時、分、秒各時間段的資訊。
- dateFromComponents:(NSDateComponents*)comps :使用comps對象包含的年、月、時、分、秒各時間字段的資訊來建立NSDate。
NSDateComponents
該對象專門用于封裝年、月、日、時、分、秒各時間字段的資訊。它隻包含了對year、month、date、day、hour、minute、second、week、weekday等各字段的setter和getter方法。
從NSDate對象中分開擷取各時間字段的數值的步驟如下:
- 1.建立NSCalendar對象。
- 2.調用NSCalendar的components:fromDate:方法擷取NSDate對象中各時間字段的數值,該方法傳回一個NSDateComponents對象。
- 3.調用NSDateComponents對象的getter方法來擷取各時間字段的數值。
使用各時間字段的數值來初始化NSDate對象的步驟如下:
- 1.建立NSCalendar對象。
- 2.建立一個NSDateComponents對象,調用該對象的setter方法來設定各時間字段的值。
- 3.調用NSCalendar的dateFromComponents:(NSDateComponents*)初始化NSDate對象,該方法會傳回一個NSDate對象。
//擷取代表公曆的Calendar對象
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
//擷取目前日期
NSDate* dt = [NSDate date];
unsigned unitFlags = NSYearCalendarUnit|NSMonthCalendarUnit|
NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|
NSSecondCalendarUnit|NSWeekdayCalendarUnit;
//擷取不同時間字段的資訊
NSDateComponents* comp = [gregorian components:unitFlags fromDate:dt];
//擷取各個時間字段的數值
NSLog(@"現在是%ld年", comp.year);
NSLog(@"現在是%ld月", comp.month);
NSLog(@"現在是%ld日", comp.day);
NSLog(@"現在是%ld時", comp.hour);
NSLog(@"現在是%ld分", comp.minute);
NSLog(@"現在是%ld秒", comp.second);
NSLog(@"現在是星期%ld", comp.weekday);
//再次建立一個NSDateComponents對象
NSDateComponents* comp2 = [[NSDateComponents alloc] init];
//設定各個時間字段的數值
comp2.year = 2013;
comp2.month = 4;
comp2.day = 12;
comp2.hour = 15;
comp2.minute = 34;
//通過NSDateComponents所包含的時間字段的數值來恢複NSDateduixiang
NSDate* date = [gregorian dateFromComponents:comp2];
NSLog(@"擷取的日期為:%@", date);
輸出結果為:
7.2.4 定時器(NSTimer)
使用定時器程式設計操作步驟:
- 1.調用NSTimer的scheduledTimerWithTimeInterval:invocation:或scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:類方法來建立NSTimer對象。調用該類方法時,需要傳入如下參數。
timeInterval:指定每隔多少秒執行一次任務。
invocation或target與selector:指定重複執行的任務。如果指定target和selector參數,則指定用某個對象的特定方法作為重複執行的任務;如果指定invocation參數,該參數需要傳入一個NSInvocation對象,其中NSInvocation對象也是封裝target和selector的,其實也是指定用某個對象的特定方法作為重複執行任務。
userInfo:該參數用于傳入額外的附加資訊。
repeats:該參數需要指定一個BOOL值,該參數控制是否需要重複執行任務。
- 2.為第一步編寫方法。
- 3.銷毀定時器。調用定時器的invalidate方法即可。
測試定時器:
@interface NSTimerTest : NSObject
@property (nonatomic, assign) int count;
- (void) start;
- (void) stop;
@end
@implementation NSTimerTest {
NSTimer* timer;
}
@synthesize count;
- (void) start {
timer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self //指定以目前對象的info方法作為執行體
selector:@selector(start)
userInfo:nil
repeats:YES]; //指定重複執行
NSLog(@"正在執行第%d次任務", self.count++);
}
- (void) stop {
NSLog(@"取消執行定時器");
[timer invalidate];
}
@end
int main(int grac, char *grav[]) {
@autoreleasepool {
NSTimerTest* test = [[NSTimerTest alloc] init];
for (int i = 0; i < 10; i++) {
[test start];
}
[test stop];
}
return 0;
}
輸出結果為:
7.3 對象複制
NSObject類提供了copy和multableCopy方法,通過這兩個方法即可複制已有對象的副本。
7.3.1 copy與mutableCopy方法
- copy方法用于複制對象的副本。通常來說,copy方法總是傳回對象的不可修改的副本,即使該對象本身是可修改的。
調用NSMutableString的copy方法,将會傳回不可修改的字元串對象。
- mutableCopy方法用于複制對象的可變副本。通常來說,mutableCopy方法總是傳回該對象可修改的副本,即使被複制的對象本身是不可修改的,調用mutableCopy方法複制出來的副本也是可修改的。
程式調用NSString的mutableCopy方法,将會傳回一個NSMutableString對象。
對複制對象的副本無論怎麼修改,原對象都不會發生改變。
NSMutableString* book = [NSMutableString
stringWithString:@"瘋狂iOS講義"];
//複制book字元串的可變副本
NSMutableString* bookCopy = [book mutableCopy];
//修改副本,對原字元串沒有任何影響
[bookCopy replaceCharactersInRange:NSMakeRange(2, 3)
withString:@"Android"];
//此處看到原字元串的值并沒有改變
NSLog(@"book的值為:%@", book);
//字元串副本發生了改變
NSLog(@"bookCopy的值為:%@", bookCopy);
NSString* str = @"fkit";
//複制str(不可變字元串)的可變副本
NSMutableString* strCopy = [str mutableCopy];
//向可變字元串後面追加字元串
[strCopy appendString:@".org"];
NSLog(@"%@", strCopy);
//調用book(可變字元串)的copy方法,程式傳回一個不可修改的副本
NSMutableString* bookCopy2 = [book copy];
//由于bookCopy2是不可修改的,是以下面的代碼将會出現錯誤
//[bookCopy2 appendString:@"aa"];
輸出結果為:
7.3.2 NSCopying與NSMutableCopy協定
雖然NSObject提供了copy和mutableCopy方法,但自定義類并不能直接調用這兩個方法來複制自身。
為了保證一個對象可以調用copy方法來複制自身的不可變副本,通常需要做如下事情:
- 讓該類實作NSCopying協定。
- 讓該類實作copyWithZone:方法。
為了保證一個對象可以調用mutableCopy方法來複制自身的可變副本,通常需要做如下事情:
- 讓該類實作NSMutableCopying協定。
- 讓該類實作mutableCopyWithZone:方法。
下面實作類的copy:
@interface FKDog : NSObject <NSCopying>
@property (nonatomic, strong) NSMutableString* name;
@property (nonatomic, assign) int age;
@end
@implementation FKDog
@synthesize name;
@synthesize age;
- (id) copyWithZone:(NSZone*) zone {
NSLog(@"--執行copyWithZone--");
FKDog* dog = [[[self class] allocWithZone:zone] init];
dog.name = self.name;
dog.age = self.age;
return dog;
}
@end
int main(int grac, char *grav[]) {
@autoreleasepool {
FKDog* dog1 = [[FKDog alloc] init];
dog1.name = [NSMutableString stringWithString:@"旺财"];
dog1.age = 20;
FKDog* dog2 = [dog1 copy];
dog2.name = [NSMutableString stringWithString:@"snoopy"];
dog2.age = 12;
NSLog(@"dog1的名字為:%@", dog1.name);
NSLog(@"dog1的年齡為:%d", dog1.age);
NSLog(@"dog2的名字為:%@", dog2.name);
NSLog(@"dog2的年齡為:%d", dog2.age);
}
return 0;
}
協定系統自帶!
輸出結果為:
- 當程式調用上述類的copy方法來複制自身時,底層實際上調用了copyWithZone:方法來執行實際的複制操作。因為此處的類沒有提供對應的不可變類,自然也就無法複制不可變的該類的對象。如果程式為該類提供了不可變類,當然還是應該讓該類的copyWithZone:傳回不可變的該類的對象。
- 如果重寫copyWithZone:方法時,其父類已經實作NSCopying協定,并重寫過copyWithZone:方法,那麼子類重寫copyWithZone:方法應先調用父類的copy方法複制從父類繼承得到的成員變量,然後對子類定義的成員變量進行指派。
假如父類已經重寫copyWithZone:方法,那麼子類重寫copyWithZone:方法的格式如下:
- (void) copyWithZone: (NSZone*) zone {
id obj = [super copy];
//對子類定義的成員變量進行指派。
...
return obj;
}
7.3.3 淺複制與深複制
淺複制(shallow copy)
當對象的執行個體變量時指針變量時,如果程式隻是複制該指針的位址,而不是真正複制指針所指向的對象,這種方式就被稱為“淺複制”。
淺複制出來的兩個對象是兩個指針變量,他們指向的是同一個位址。
深複制(deep copy)
深複制不僅會複制對象本身,而且會“遞歸”複制每個指針類型的執行個體變量,直到兩個對象沒有任何公共的部分。
将上述的copyWithZone:改為深複制:
- (id) copyWithZone: (NSZone*) zone {
NSLog(@"--執行copyWithZone--");
FKDog* dog = [[[self class] allocWithZone:zone] init];
dog.name = [self.name mutableCopy];
dog.age = self.age;
return dog;
}
上面程式中并沒有簡單地将被複制對象的name執行個體變量的值賦給新對象的name執行個體變量,而是先将原對象name執行個體變量複制了一份可變副本,再将該可變副本的值賦給新對象的name執行個體變量。這樣就保證了原對象和新對象沒有任何公共部分,這就實作了深複制。
7.3.4 setter方法的複制選項
前面介紹合成setter和getter方法時提到可以使用copy訓示符,copy訓示符就是指定當程式調用setter方法複制時,實際上是将傳入參數的副本賦給程式的執行個體變量。
定義合成getter、setter方法時并沒有提供mutableCopy訓示符,隻有copy訓示符。
系統預設的setter方法如下:
例如setName:
- (void) setName: (NSMutableString*) aname {
name = [aname copy];
}
copy方法預設是複制該對象的不可變副本,雖然程式傳入的NSMutableString,但程式調用該參數的copy方法得到的是不可變副本。