OC学习:Foudation框架
文章目录
字符串
在OC中,NSString代表字符序列不可变的字符串,NSMutableString代表字符序列可变的字符串
创建字符串
下面是创建NSString的几种方法
-
字面量语法
objectivecNSString* s1 = @"Hello"; NSString* s2 = @"张三";编译时创建,存储在常量区,全局共享,性能最佳
-
类方法
-
stringWithFormat-格式化创建
objectivecNSString* s3 = [NSString stringWithFormat:@"%@, %@!", s1, s2]; -
stringWithString-从另一个字符串创建
;NSString* s4 = @"123"; NSString* s5 = [NSString stringWithString : s4]; -
stringWithUTF8String-从C字符串创建
objectivecchar* s6 = "Hello"; NSString* s7 = [NSString stringWithUTF8String : s6]; -
stringWithContentsOfURL:encoding:error
objectivecNSString *str = [NSString stringWithContentsOfFile:@"/path/file.txt" encoding:NSUTF8StringEncoding error:nil];在上面的类方法中,本身就包括了实例方法中的初始化方法
-
-
空字符串
NSString* str = [[NSString alloc] init];
下面是创建NSMutableString的几种方法
-
创建空的可变字符串
objectivecNSMutableString *mStr = [NSMutableString string]; NSMutableString *mStr = [[NSMutableString alloc] init]; -
从已有字符串创建
objectivecNSMutableString *mStr = [NSMutableString stringWithString:@"Hello"]; NSMutableString *mStr = [[NSMutableString alloc] initWithString:@"Hello"]; -
指定初始容量
objectivecNSMutableString *mStr = [NSMutableString stringWithCapacity:10];
三种实现方法
NSString的三种实现方法为_NSCFConstantString,_NSTaggedPointerString, _NSCFString
- 常量字符串(
__NSCFConstantString)
创建方式:字面量 @"..."、[[NSString alloc] init](空字符串)等。
特征:存储在程序的常量区(__TEXT 段),全局共享,生命周期与程序相同,无需内存管理,访问速度最快。
示例:NSString *str = @"hello";
- Tagged Pointer 字符串(
NSTaggedPointerString)
创建方式:通过 stringWithFormat: 等动态方式生成的短字符串(通常长度 ≤ 某个阈值(七个字节以内))。
特征:将字符串内容直接编码在指针值中,不分配堆内存或者栈内存,无引用计数开销,性能极高。
示例:NSString *str = [NSString stringWithFormat:@"he"];(如果内容足够短)
- 普通动态字符串(
__NSCFString)
创建方式:较长的字符串、可变字符串(NSMutableString)、或通过 stringWithFormat: 等生成的长字符串。
特征:在堆上分配内存,支持任意长度,使用引用计数管理,可变为可变字符串(NSMutableString 也是其子类)。
示例:NSString *str = [NSString stringWithFormat:@"hello world, this is a long sentence"];
字符串的常用方法
objectivec
//
// zifuchuan.m
// Study
//
// Created by 王子鸣 on 2026/3/26.
//
#import "zifuchuan.h"
@implementation zifuchuan
@end
int main(int argc, char* argv[]) {
//不可变字符串
NSString* s1 = @"Hello";
NSString* s2 = @"张三";
NSString* s3 = [NSString stringWithFormat:@"%@, %@!", s1, s2];
NSLog(@"%@", s3);
NSLog(@"字符串长度为%lu", (unsigned long) s3.length);//计算字符串长度
NSString* s4 = [s3 uppercaseString];//全转变为大写字母
NSString* s5 = [s3 lowercaseString];//全转变为小写字母
NSLog(@"%@", s4);
NSLog(@"%@", s5);
NSString* s6 = [s3 stringByAppendingString:@"你好"];//往字符串里增加内容
NSLog(@"%@", s6);
NSString* s7 = [s3 substringToIndex:5];//截取前五个字符
NSLog(@"%@", s7);
NSString* s8 = [s3 substringFromIndex:5];//从第五个字符开始截取
NSLog(@"%@", s8);
NSString* s9 = [s2 substringWithRange:NSMakeRange(0, 1)];//从索引0开始截取1个字符
NSLog(@"%@", s9);
//可变字符串
NSMutableString* s10 = [NSMutableString stringWithString:@"起源"];
NSLog(@"%@", s10);
[s10 appendString:@"追加"];//追加内容
NSLog(@"%@", s10);
[s10 insertString:@"插入" atIndex:3];//在索引3插入内容
NSLog(@"%@", s10);
[s10 replaceCharactersInRange:NSMakeRange(2, 3) withString:@"替换"];//将索引2之后的3个字符替换
NSLog(@"%@", s10);
[s10 deleteCharactersInRange:NSMakeRange(2, 3)];//将索引2之后的3个字符删除
NSLog(@"%@", s10);
return 0;
}
对象复制
copy和mutablecopy
NSObject提供了copy和mutablecopy方法,copy方法用于复制对象的副本,通常总是返回对象不可修改的副本,即使对象本身可以修改,mutablecopy用于复制对象的可变副本,通常总是返回对象可修改的副本,即使对象本身是不可修改的
上述两个方法返回的都是复制对象的副本,所以对复制的副本进行修改时,原对象通常不受影响。
objectivec
NSMutableString* book = [NSMutableString stringWithString:@"疯狂iOS讲义"];
//复制book(可变)字符串的可变副本
NSMutableString* bookCopy = [book mutableCopy];
[bookCopy replaceCharactersInRange:NSMakeRange(2, 3) withString:@"android"];
//修改副本,对原字符串没有影响
NSLog(@"book的值为:%@", book);
//副本字符串发生了改变
NSLog(@"bookCopy的值为:%@", bookCopy);
输出结果是疯狂iOS讲义和疯狂android讲义,可见,修改副本并不会改变原对象
objectivec
NSString* str = @"fkos";
//复制不可变字符串str的可变副本
NSMutableString* strCopy = [str mutableCopy];
//向可变字符串后追加字符串
[strCopy appendString:@".org"];
NSLog(@"%@", strCopy);
//调用book的copy方法,返回一个不可修改的副本
NSMutableString* bookCopy2 = [book copy];
//若此时对bookCopy进行修改,编译时不会报错,但是运行后代码就会出错,即下面注释的代码
//[bookCopy2 appendString:@"very good"];
即使str不可变,但是mutablecopy后的strCopy可以修改,即使book是可变的,但是copy后的bookCopy2就是不能修改
NSCopying和NSMutableCopying协议
copy和mutabCopy确实很方便,但是对于我们自己定义的类,我们用不了这两个方法(运行中会显示找不到(mutable)copyWithZone方法),因为需要调用这两个方法,所以我们要让这个类实现NS(mutable)Copying协议和实现(mutable)copyWithZone方法
objectivec
@interface FKDog : NSObject <NSCopying>
@property (nonatomic, strong) NSMutableString* name;
@property (nonatomic, assign) int age;
-(id) copyWithZone:(NSZone*)zone;
@end
objectivec
@implementation FKDog
- (id) copyWithZone : (NSZone*)Zone
{
FKDog* dog = [[[self class] allocWithZone: Zone]init];
dog.name = self.name;
dog.age = self.name;
return dog;
}
@end
objectivec
FKDog* dog1 = [FKDog new];
dog1.name = [NSMutableString stringWithString:@"旺财"];
dog1.age = 20;
FKDog* dog2 = [dog1 copy];
dog2.name = [NSMutableString stringWithString:@"来福"];
dog2.age = 12;
NSLog(@"dog1的名字是%@", dog1.name);
NSLog(@"dog1的年龄是%d", dog1.age);
NSLog(@"dog2的名字是%@", dog2.name);
NSLog(@"dog1的年龄是%d", dog2.age);
这样我们就可以实现自定义类的复制了
深浅拷贝
浅拷贝仅仅是复制原对象的地址,即原对象和副本使用一个内存地址,修改任何一个都会影响另外一个
深拷贝是将原对象的内容复制放在一个新的内存地址,两者互不影响
- 非容器类比如NSString,NSNumber等包装类
对不可变对象(如 NSString)调用 copy,由于内容不可变,系统直接返回自身,而不是创建新对象。
对可变对象(如 NSMutableString)调用 copy,返回一个不可变的副本(NSString),并复制内容。
对任何对象调用 mutableCopy,都会返回一个新的可变副本(如 NSMutableString),即使原对象是不可变的,也会创建新对象 并复制内容。
-
容器类比如NSArray,NSSet,NSDictionary
对不可变容器(如
NSArray)调用copy,通常返回自身(优化)。对不可变容器调用
mutableCopy,返回一个新的可变容器(如NSMutableArray),但元素仍是原数组中的对象(浅拷贝)。对可变容器(如
NSMutableArray)调用copy,返回一个新的不可变容器,元素仍是原容器中的对象。对可变容器调用
mutableCopy,返回一个新的可变容器,元素仍是原容器中的对象。
三大容器
数组(Array)
数组用于存储有序的对象集合,允许重复元素。
不可变数组:NSArray
创建后内容不可变。
常用创建方式:字面量 @[obj1, obj2]、arrayWithObjects:、arrayWithArray: 等。
objectivec
NSArray* arr = @[@4, @3, @2, @1];
访问:下标 array[index] 或 objectAtIndex:。
常用方法:count、containsObject:、indexOfObject:、subarrayWithRange:、sortedArrayUsingSelector: 等。
三种排序方法
- sortedArrayUsingFunction
objectivec
@implementation shuzu
NSInteger inSort(id num1, id num2, void* context) {
int val1 = [num1 intValue];
int val2 = [num2 intValue];
if (val1 > val2) {
return NSOrderedAscending;
}else if (val1 < val2) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}
@end
arr = [arr sortedArrayUsingFunction:inSort context:nil];
-
sortedArrayUsingSelector
objectivecarr = [arr sortedArrayUsingSelector:@selector(compare:)]; -
sortedArrayUsingComparator
objectivecarr = [arr sortedArrayUsingComparator:^(id obj1, id obj2){ int val1 = [obj1 intValue]; int val2 = [obj2 intValue]; if (val1 > val2) { return NSOrderedAscending; }else if (val1 < val2) { return NSOrderedDescending; } else { return NSOrderedSame; } }];
可变数组:NSMutableArray
继承自 NSArray,支持动态增删改。
objectivec
NSMutableArray* arr1 = [@[@1, @2, @3, @4] mutableCopy];
NSMutableArray* arr1 = [NSMutableArray arrayWithObjects:@1, @2, @3, @4, nil];
添加:addObject:、insertObject:atIndex:。
objectivec
[arr1 addObject:@5];
删除:removeObject:、removeObjectAtIndex:、removeLastObject。
替换:replaceObjectAtIndex:withObject: 或下标赋值。
objectivec
[arr1 replaceObjectAtIndex:2 withObject:@7];
遍历方式
快速枚举 for (id obj in array)
objectivec
for (id object in arr) {
NSLog(@"%@", object);
}
Block 枚举 enumerateObjectsUsingBlock:
索引循环 for (NSInteger i = 0; i < array.count; i++)
适用场景
需要保持元素顺序、允许重复,或需要通过索引快速访问。
集合(Set)
集合存储无序、唯一的对象,常用于去重和快速成员检测。
- 不可变集合:
NSSet
创建:[NSSet setWithObjects:obj1, obj2, nil] 或 [NSSet setWithArray:]。
objectivec
NSSet* set1 = [NSSet setWithObjects : @1, @2, @3, @3, nil];
NSArray* arr1 = @[@1, @2, @3, @3];
NSSet* set2 = [NSSet setWithArray: arr1];
检测:containsObject:(O(1) 平均)。
获取所有对象:allObjects。
- 可变集合:
NSMutableSet
objectivec
NSMutableSet* set3 = [NSMutableSet setWithArray:arr1];
添加:addObject:(已存在则不添加)。
objectivec
[set3 addObject:@2];
[set3 addObject:@4];
删除:removeObject:。
objectivec
[set3 removeObject:@2];
集合运算:unionSet:(并集)、intersectSet:(交集)、minusSet:(差集)。
objectivec
NSMutableSet* set4 = [NSMutableSet setWithObjects : @1, @3, @3, @4, @5,nil];
NSMutableSet* set5 = [NSMutableSet setWithObjects : @1, @2, @3, nil];
NSMutableSet* set6 = [set5 mutableCopy];
[set6 unionSet : set4];
NSLog(@"%@", set6);
NSMutableSet* set7 = [set5 mutableCopy];
[set7 intersectSet:set4];
NSLog(@"%@", set7);
遍历方式
快速枚举:for (id obj in set)
objectivec
for (id object in set3) {
NSLog(@"%@", object);
}
Block 枚举:enumerateObjectsUsingBlock:
objectivec
[set3 enumerateObjectsUsingBlock:^(id obj, BOOL* stop) {
if ([obj isEqual : @3]) {
NSLog(@"已找到");
*stop = YES;
} else {
NSLog(@"%@", obj);
}
}];
适用场景
需要保证元素唯一、快速判断是否存在、或进行集合运算(如并集、交集)。
字典(Dictionary)
字典存储键值对 (key-value),键唯一,值可以是任意对象。键通常使用 NSString,但也可以是任何遵守 NSCopying 协议的对象。
- 不可变字典:
NSDictionary
字面量创建:@{key1: value1, key2: value2}。
objectivec
NSDictionary *person = @{
@"name": @"张三",
@"age": @25,
@"city": @"北京"
};
取值:dict[key] 或 objectForKey:。
objectivec
NSString *name = person[@"name"];
NSNumber *age = person[@"age"];
NSString *city = [person objectForKey:@"city"];
常用方法:allKeys、allValues、count、isEqualToDictionary:。
- 可变字典:
NSMutableDictionary
添加/修改:setObject:forKey: 或 dict[key] = value。
objectivec
[mutablePerson setObject:@"男" forKey:@"gender"];
mutablePerson[@"age"] = @26;
删除:removeObjectForKey:、removeAllObjects。
objectivec
[mutablePerson removeObjectForKey:@"city"];
遍历方式
快速枚举遍历键:for (id key in dict)
objectivec
for (NSString *key in mutablePerson) {
NSLog(@"快速枚举: %@ = %@", key, mutablePerson[key]);
}
Block 枚举:enumerateKeysAndObjectsUsingBlock:
objectivec
[mutablePerson enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
NSLog(@"Block 枚举: %@ = %@", key, value);
if ([key isEqualToString:@"job"]) {
*stop = YES; // 找到 job 后停止
}
}];
适用场景
需要通过唯一标识符(键)快速查找数据,如用户配置、网络请求参数等。