Foundation 框架提供的基礎類是 OC 開發的語言級運行時支持。本文系統梳理字符串、數組、數值包裝、結構體包裝六大核心類簇,對比不可變/可變語義、內存管理、性能特徵、現代字面量語法與經典工廠方法,並給出工程級最佳實踐。
NSString` / NSMutableString`NSString`// 現代字面量語法 (編譯期常量,存儲在數據段) NSString *str = @"Hello 郭String"; // 經典工廠方法 NSString *str2 = [NSString stringWithFormat:@"hehe %@ %@", @"hhh", @"jjj"]; // 核心屬性 NSUInteger len = str.length; // UTF-16 代碼單元數,非字符數(Emoji 佔2) // 子串提取 NSString *sub1 = [str substringFromIndex:5]; // 從索引 5 到末尾 NSString *sub2 = [str substringToIndex:5]; // 從開頭到索引 5(不含) NSRange range = NSMakeRange(2, 3); NSString *sub3 = [str substringWithRange:range]; // 指定範圍 // 拼接 (返回新字符串) NSString *cat1 = [str stringByAppendingString:@"IOS"]; NSString *cat2 = [str stringByAppendingFormat:@" %@ %@", @"A", @"B"]; // 替換 (返回新字符串) NSString *replaced = [str stringByReplacingOccurrencesOfString:@"String" withString:@"World"]; // 比較 BOOL equal = [str isEqualToString:@"Hello"]; // 內容比較 BOOL hasPrefix = [str hasPrefix:@"Hello"]; // 前綴 BOOL hasSuffix = [str hasSuffix:@"png"]; // 後綴 // 關鍵:NSString 不可變,所有「修改」操作實際創建新對象
NSMutableString` (NSString 子類)NSMutableString *mStr = [NSMutableString stringWithString:@"Hello"]; // 基於現有創建 // 或 [NSMutableString string] 創建空串 // 就地修改 (不創建新對象) [mStr appendString:@"Guozai"]; // 追加字符串 [mStr appendFormat:@" %d", 123]; // 格式化追加 [mStr deleteCharactersInRange:NSMakeRange(4, 1)]; // 刪除範圍 [mStr replaceCharactersInRange:NSMakeRange(3, 2) withString:@"YY"]; // 替換 [mStr insertString:@"TT" atIndex:2]; // 插入 // 繼承 NSString 所有只讀方法 NSUInteger len = mStr.length; BOOL hasPre = [mStr hasPrefix:@"He"];
| 場景 | 推薦類型 | 理由 |
|---|---|---|
| 常量、配置、傳遞給 API、多線程共享 | NSString | 線程安全、語義清晰、編譯器優化 (常量合併) |
| 頻繁拼接、構建大字符串、逐字符構建 | NSMutableString | 避免大量臨時對象分配/釋放,性能優勢顯著 |
| JSON 序列化、網絡請求體構建 | NSMutableString 或 NSOutputStream | 流式寫入更適合超大數據 |
NSArray` / NSMutableArray`NSArray`// 現代字面量
NSArray *arr = @[@"Guozai", @"Guo", @"Zaiguo"]; // 以 nil 結尾 (字面量自動處理)
// 經典工廠
NSArray *arr2 = [NSArray arrayWithObjects:@"A", @"B", @"C", nil];
// 訪問
id first = arr.firstObject; // nil 安全
id last = arr.lastObject;
id obj = arr[1]; // 下標語法 (現代)
id obj2 = [arr objectAtIndex:1]; // 經典方法
// 遍歷
for (id obj in arr) { ... } // 快速枚舉 (推薦)
for (NSUInteger i=0; i
2. 可變數組 NSMutableArray` (NSArray 子類)
NSMutableArray *mArr = [NSMutableArray arrayWithArray:arr]; // 基於現有創建
// 或 [NSMutableArray array] / [NSMutableArray arrayWithCapacity:10]
// 增
[mArr addObject:@"Guoguo"]; // 尾部添加
[mArr insertObject:@"New" atIndex:0]; // 指定位置插入
// 刪
[mArr removeObjectAtIndex:2]; // 按索引刪除
[mArr removeLastObject]; // 刪除最後
[mArr removeObject:@"Guo"]; // 按值刪除 (第一個匹配)
[mArr removeObjectsInArray:@[@"A",@"B"]]; // 批量刪除
// 改
[mArr exchangeObjectAtIndex:0 withObjectAtIndex:mArr.count-1]; // 交換首尾
mArr[0] = @"NewValue"; // 下標賦值 (現代語法)
// 查
NSUInteger idx = [mArr indexOfObject:@"Guozai"]; // 線性查找 O(n)
BOOL contains = [mArr containsObject:@"Guo"]; // 同 indexOfObject != NSNotFound
3. 實戰:可變數組管理模型對象 (圖書系統)
// Book 模型
@interface Book : NSObject
@property (copy) NSString *name;
@property (assign) CGFloat price;
- (instancetype)initWithName:(NSString *)name price:(CGFloat)price;
@end
// 使用
Book *b1 = [[Book alloc] initWithName:@"Guozai1" price:10];
Book *b2 = [[Book alloc] initWithName:@"Guozai2" price:15];
Book *b3 = [[Book alloc] initWithName:@"Guozai3" price:13];
NSMutableArray *books = [NSMutableArray arrayWithObjects:b1, b2, b3, nil];
// 添加/刪除
[books addObject:[[Book alloc] initWithName:@"Guozai4" price:12]];
[books removeObjectAtIndex:2];
// 遍歷輸出
for (Book *b in books) {
NSLog(@"%@, %.2f", b.name, b.price);
}
// 查找
for (Book *b in books) {
if ([b.name isEqualToString:@"Guozai3"]) {
NSLog(@"Price: %f", b.price);
}
}
// 排序:按價格降序 (冒泡演示,實際用 sortUsingComparator:)
for (int i=0; i
三、 數值包裝:NSNumber` — 基礎類型與對象橋接
// 裝箱:基本類型 → 對象
NSNumber *numInt = @100; // 現代語法 (編譯器自動推導類型)
NSNumber *numDbl = @3.14;
NSNumber *numBool = @YES;
// 等價經典: [NSNumber numberWithInt:100], numberWithDouble:, numberWithBool:
// 拆箱:對象 → 基本類型
int val = [numInt intValue];
double d = [numDbl doubleValue];
BOOL b = [numBool boolValue];
// 通用: [numInt integerValue], longLongValue, floatValue 等
// 集合存儲基本類型
NSMutableArray *arr = [NSMutableArray array];
[arr addObject:@42]; // 自動裝箱
int x = [arr[0] intValue]; // 手動拆箱
// 比較
NSComparisonResult cmp = [numInt compare:@200]; // -1/0/1
BOOL eq = [numInt isEqualToNumber:@100]; // 值相等
四、 結構體包裝:NSValue` — 非對象類型入集合
// CGPoint / CGSize / CGRect / CGAffineTransform 等 Core Graphics 結構體
CGPoint pt = CGPointMake(10, 20);
NSValue *val = [NSValue valueWithPoint:pt]; // 裝箱
CGPoint pt2 = [val pointValue]; // 拆箱
// 字符串化 (調試用)
NSLog(@"%@", NSStringFromPoint(pt2)); // 輸出 "{10, 20}"
// 其他結構體
CGSize sz = CGSizeMake(100, 200);
NSValue *szVal = [NSValue valueWithSize:sz];
CGSize sz2 = [szVal sizeValue];
NSLog(@"%@", NSStringFromSize(sz2)); // "{100, 200}"
// 自定義結構體 (需手動編碼/解碼)
typedef struct { int x; int y; } MyPoint;
MyPoint mp = {5, 6};
NSData *data = [NSData dataWithBytes:&mp length:sizeof(mp)]; // 序列化為 Data
[arr addObject:data]; // 存入數組
// 取出時: MyPoint mp2; [data getBytes:&mp2 length:sizeof(mp2)];
五、 核心設計模式總結
模式 體現 優勢
類簇 NSString 實際是 __NSCFString 等私有子類統一接口,運行時根據數據特徵選擇最優實現 (如單字符優化、大字符串優化)
不可變/可變雙重體系 NSArray`/NSMutableArray` 等語義明確,線程安全 (不可變),性能優化 (可變就地修改)
字面量語法 @[], @{}, @()編譯期類型推導,生成靜態常量或優化調用,代碼簡潔
裝箱/拆箱 NSNumber`, NSValue`基本類型/結構體無縫進入對象體系 (集合、KVC、Archiving)
最佳實踐:默認使用不可變類型 (NSString, NSArray, NSDictionary) 並配合現代字面量語法;僅在性能分析證明瓶頸或邏輯確需就地修改時 使用可變對應類型。利用 @() 自動裝箱基本類型,NSValue 包裝結構體,讓所有數據統一為對象流入集合/KVC/歸檔管線。記住:NSMutableString 等可變類是其不可變父類的子類,可直接傳遞給接收父類的參數(但語義上需謹慎)。