023-Foundation框架(上)-OC笔记

/ 0

学习目标

1.【理解】NSString

2.【了解】NSString的常用方法

3.【了解】NSRange

4.【了解】NSMutableString

5.【掌握】NSArray

6.【了解】NSArray的常用方法

7.【掌握】遍历数组的三种方式

8.【了解】NSArray与字符串

9.【掌握】NSMutableArray

一、NSString

在OC中,使用NSString类型的对象来保存一个字符串对象的地址,OC字符串必须要使用 @ 前缀。NSString其实是Foundation框架中的一个类,字符串以NSString对象的形式保存。如果是以字符串常量去初始化一个NSString指针,那么这个字符串常量是存储在常量区之中的。如果是以调用NSString的类方法来得到一个字符串对象,这个对象就创建在堆区。并且一旦在内存中(无论堆区、常量区)创建了一个字符串对象,这个字符串对象的字符内容就无法修改。

//OC字符串常量需要加@,并且这种方式创建的字符串存储在常量区,不需要自己释放内存
NSString *str1 = @"OC字符串";//常量区

//C语言的字符串转换为OC字符串
NSString *str2 = [[NSString alloc] initWithUTF8String:"C字符串"];
const char *strc = str2.UTF8String;//将OC字符串转为C语言字符串
NSUInteger length = str2.length;//计算字符串长度

//类方法格式化创建一个字符串对象
NSString *str3 = [NSString stringWithFormat:@"格式"];//堆区

//构造方法创建字符串对象
NSString *str4 = [[NSString alloc] initWithString:@"OC字符串"];//常量区

//对象方法格式化创建字符串对象
NSString *str5 = [[NSString alloc] initWithFormat:@"拼接字符串%@",str4];//堆区

二、NSString的常用方法

从文件中读取或写入字符串

//创建一个字符串常量
NSString *str1 = @"我爱北京天安门";

/*
 将字符串写入文件
 writeToFile: 参数为将存储字符串的文件路径
 atomically: 参数为YES(安全,低效) NO(不安全,高效)
 encoding: 参数为字符编码,一般为NSUTF8StringEncoding
 error: 参数为NSError类型的二级指针,可以传nil不接受错误信息
 返回值是BOOL类型,如果成功返回YES
 */
NSError *err = nil;
//将str1写入到指定文件并接收是否写入成功
BOOL b = [str1 writeToFile:@"/Users/itcast/Desktop/text.txt" atomically:NO encoding:NSUTF8StringEncoding error:&err];
//判断是否写入成功,失败则输出错误信息
if (err == nil) {
    NSLog(@"写入成功");
}else {
    NSLog(@"%@",[err localizedDescription]);
}

//调用类方法创建NSURL对象,存储url(统一资源定位符)
NSURL *url = [NSURL URLWithString:@"file:///Users/itcast/Desktop/text.txt"];

//将url里的字符串存储到str
NSString *str3 = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

//存储资源的文件
NSURL *url1 = [NSURL fileURLWithPath:@"/Users/itcast/Desktop/text1.txt"];

//将字符串写入文件
[str3 writeToURL:url1 atomically:YES encoding:NSUTF8StringEncoding error:nil];

//从文件读取字符串存储到字符串
NSString *str2 = [NSString stringWithContentsOfFile:@"/Users/itcast/Desktop/text.txt" encoding:NSUTF8StringEncoding error:nil];
/*
 一般写入字符串到文件的方法返回值类型都是BOOL,如果返回YES则表示写入成功,返回NO表示写入失败,并且我们可以使用NSError类对象来接受失败错误信息。
 */

字符串的比较和判断

//比较两个字符串的大小
//NSComparisonResult的定义
//typedef NS_ENUM(NSInteger, NSComparisonResult) {
//    NSOrderedAscending = -1L,//第一个小于第二个
//    NSOrderedSame,//两个字符串内容相等
//    NSOrderedDescending//第一个大于第二个
//};

NSString *str1 = @"abc";
NSString *str2 = @"Abc";

//是比较两个字符串的字符的ASCII码大小
NSComparisonResult res = [str1 compare:str2];
NSLog(@"res = %ld",res);//res = 1

//忽略大小写比较
NSComparisonResult res1 = [str1 compare:str2 options:NSCaseInsensitiveSearch];
NSLog(@"res1 = %ld",res1);//res = 0

//判断两个字符串是否相等
BOOL res2 = [str1 isEqualToString:str2];
NSLog(@"res = %d",res2);//res = 0

//判断字符串的前缀、后缀
NSString *str = @"/User/itcast/Desktop/xx.mp3";

//判断字符串是否以 http:// 开头
BOOL res3 = [str hasPrefix:@"http://"];

//判断字符串是否以 .mp3 结尾
BOOL res4 = [str hasSuffix:@".mp3"];

//在字符串中搜索子串第一次出现的范围
NSString *str3 = @"我爱你广州小蛮腰,广州爱我的钞票";
NSRange res5 = [str rangeOfString:@"广州"];

//输出子串起始下标和长度
NSLog(@"location = %ld length = %ld",res5.location,res5.length);//location = 3 length = 2

//在字符串中搜索子串最后一次出现的范围
NSRange res6 = [str rangeOfString:@"广州" options:NSBackwardsSearch];
//输出子串最后一次出现的下标和长度
NSLog(@"location = %ld length = %ld",res6.location,res6.length);//location = 9 length = 2

字符串的截取,从一个字符串中,取出一个子字符串来

NSString *str = @"jackloverose";

//取出指定单个字符
unichar ch = [str characterAtIndex:0];
NSLog(@"ch = %C",ch);//ch = j

//从字符中指定的下标截取到最后
NSString *newStr1 = [str substringFromIndex:4];
NSLog(@"newStr1 = %@",newStr1);//newStr = loverose

//从第0个元素截取到指定的下标
NSString *newStr2 = [str substringToIndex:4];
NSLog(@"newStr2 = %@",newStr2);//newStr = jack

//从字符串中截取一个范围的子字符串
NSString *newStr3 = [str substringWithRange:NSMakeRange(4, 4)];
NSLog(@"newStr3 = %@",newStr3);//newStr = love

字符串的替换,将字符串中符合要求的子串替换成另外的字符串

NSString *str = @"admin#6ag.cn";
//将str字符串的所有的@"#"替换为@"@",产生新的字符串,不会修改原先字符串
NSString *newStr = [str stringByReplacingOccurrencesOfString:@"#" withString:@"@"];
NSLog(@"%@",newStr);//admin@6ag.cn

将字符串转为一些基本数据类型

@property (readonly) double doubleValue;
@property (readonly) float floatValue;
@property (readonly) int intValue;
@property (readonly) NSInteger integerValue NS_AVAILABLE(10_5, 2_0);
@property (readonly) long long longLongValue NS_AVAILABLE(10_5, 2_0);
@property (readonly) BOOL boolValue NS_AVAILABLE(10_5, 2_0);

//例如将字符串转为int类型再相加
NSString *str1 = @"100fdf";
//当字符串字面量不是纯数字,能转多少是多少。这里忽略数字后的字面
NSString *str2 = @"200a";
//属性可以直接用点语法调用
int result = str1.intValue + str2.intValue;
NSLog(@"result = %d",result);// result = 300

C语言字符串和OC字符串互转

//C语言的字符串转换为OC字符串
NSString *str2 = [NSString stringWithUTF8String:"C字符串"];
//将OC字符串转为C语言字符串
const char *strc = str2.UTF8String;

NSUInteger length = str2.length;//计算字符串长度

三、NSRange

NSRange是Foundation框架中比较常用的结构体,一个NSRange结构体变量表示一段范围。通常情况下,用来表示一个子字符串在主字符串中的范围。它的定义如下:

typedef struct _NSRange {
    //NSUInteger是unsigned long
    NSUInteger location;//表示这个范围的起始位置下标
    NSUInteger length;//表示该范围内的长度
} NSRange;

//第一种创建方法
NSRange range1;
range1.location = 7;
range1.length = 3;
//第二种创建方法
NSRange range2 = {7,3};
//第三种创建方法
NSRange range3 = {.location = 7,.length = 3};

//第四种创建方法,使用函数创建,推荐使用此方法
NSRange range4 = NSMakeRange(7, 3);

//最笨的输出方法
NSLog(@"{%lu, %lu}",range1.location,range1.length);// {7, 3}

//使用框架提供的函数以字符串形式输出
NSLog(@"%@",NSStringFromRange(range1));// {7, 3}

四、NSMutableString

NSString字符串的特点是恒定性,一旦创建字符串对象在内存之中,这个字符串对象的内容就无法更改。当我们重新为一个 NSString指针变量赋值一个字符串的时候,会先在常量区查找是否有相同内容的字符串,如果有就直接指向,如果没有才会创建字符串。那么这样就会有一个问题,当我们做大批量的字符串拼接的时候,就会特别的消耗性能和时间。

NSString的硬伤

NSString *str = @"";
for (int i = 0; i < 100000; i++) {
    str = [str stringByAppendingString:[NSString stringWithFormat:@"%d",i]];
}
//亲测,跑了一分多钟才输出横线,可想而知手机得多卡
NSLog(@"-----------------");

Foundation提供了一个NSString的子类NSMutableString,NSMutableString对NSString做的最大的扩展就是,NSMutableString对象用来存储字符串的时候,这个对象中存储的字符串内容是可以更改的。这样在我们做字符串拼接的时候,就不会产生一个又一个的字符串对象,而是直接修改这个NSMutableString对象了。

NSMutableString *str = [NSMutableString string];
//追加字符串,不会新创建对象
[str appendString:@"jack"];
//以格式控制符的格式拼接追加字符串
[str appendFormat:@"%d",1];
NSLog(@"%@",str);//jackrose

//将NSMutableString字符串转为NSString字符串
NSString *str1 = [NSString stringWithString:str];

解决NSString的硬伤

NSMutableString *str = [NSMutableString string];
for (int i = 0; i < 100000; i++) {
    [str appendFormat:@"%d",i];
}
//刷一下就出来了,因为对象只有一个,每次拼接都是修改同一个对象
NSLog(@"-----------------");

总结:

平时我们使用字符串的时候还是尽量使用NSString,因为NSString的恒定性,当我们同一个字符串多次使用的时候,效率就很高。当我们做大批量拼接字符串的时候才用NSMutableString。

五、NSArray

C语言中的数组特点:

元素的类型一致,创建一个C语言的数组,这个数组中可以存储的数据的元素的类型必须是一致的。C语言数组的长度是固定的,一旦创建数组,就无法改变。C语言数组的元素无法删除、新增。OC中新增了数组类NSArray,在C语言的数组的基础之上做了很大的增强。

NSArray数组的特点:

1.只能存储OC对象,而且是可以存储任意OC对象

2.这些对象在NSArray数组中是有序存放,一个挨一个的存储。

3.NSArray数组只能存储OC对象,不能存储非OC对象。所以基本数据类型等非OC对象类型无法存储。

4.NSArray数组是不可变的,一旦初始化完毕之后,它里面的元素就永远是固定的,无法删除和新增元素

//创建一个长度为0的数组,而且无法修改
NSArray *arr1 = [NSArray array];
//创建一个长度为1的数组
NSArray *arr2 = [NSArray arrayWithObject:@"1"];
//创建一个长度为2的数组,以nil作为结束符,一定不能省略
NSArray *arr3 = [NSArray arrayWithObjects:@"1",@"2",nil,@"3",nil];

//快速创建数组的方法,不能存nil
NSArray *arr4 = @[@"jack",@"rose",@"lucy"];

NSLog(@"\n%@",arr4);
/* 输出
(
    jack,
    rose,
    lucy
)
*/

六、NSArray的常用方法

NSArray *arr = @[@"jack",@"rose",@"mark"];

//取出数组元素的两种方式
NSLog(@"%@",arr[0]);//jack
NSLog(@"%@",[arr objectAtIndex:0]);//jack

//得到NSArray数组的长度
NSUInteger count = arr.count;
NSLog(@"count = %lu",count);//count = 3

//取出元素并存储到对应对象中
NSString *str = [arr objectAtIndex:0];
NSLog(@"str = %@",str);//str = jack

//判断数组中是否包含指定元素
BOOL res = [arr containsObject:@"rose"];
NSLog(@"res = %d",res);//res = 1

//取出第一个元素
NSString *str1 = arr.firstObject;
NSLog(@"str1 = %@",str1);//str1 = jack

//取出最后一个元素
NSString *str2 = arr.lastObject;
NSLog(@"str2 = %@",str2);//str2 = mark

//查找指定的元素在数组中第一次出现的下标,找不到返回NSNotFound
NSUInteger index = [arr indexOfObject:@"rose"];
NSLog(@"index = %lu",index);//index = 1

七、遍历数组的三种方式

第一种,遍历数组,使用常规for循环

for (int i = 0; i < arr.count; i++) {
    NSLog(@"%@",arr[i]/*或 [arr objectAtIndex:i]*/);
}

第二种,遍历数组,使用增强for循环

for (NSString *obj in arr){
    //obj 叫 迭代变量
    NSLog(@"%@",obj);
}
/*
 增强for循环遍历NSArray数组的原理:
 将NSArray数组中的每 1 个元素从头到尾的赋值给迭代变量,并执行循环体。
 当将最后1个元素赋值给迭代变量并执行完循环体后,就自动结束循环。
 将第 0 个元素赋值给迭代变量,执行循环体。
 将第 1 个元素赋值给迭代变量,执行循环体。
 将第 2 个元素赋值给迭代变量,执行循环体。
 ......!
 将最后 1 个元素赋值给迭代变量,执行循环体。
 结束增强 for 循环。
 
 增强 for 循环使用注意:
 迭代变量的类型要和数组的元素的类型一致,否则在执行的时候如果类型不一致,会出现操作错误。
 如果数组中的元素的类型不一致,就使用 id 万能指针。
 增强 for 循环,遍历出来的迭代变量直接就是数组的元素的值,不是下标。
 */

第三种,遍历数组,使用block

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    //obj:代表遍历出来的元素的值
    //idx:代表遍历出来的元素下标
    //如果希望停止遍历,就给stop指针指向的变量赋值为NO
    NSLog(@"idx = %lu obj = %@",idx,obj);
    
    //当遍历到下标为2的元素,就停止循环
    if (idx == 1) {
        *stop = YES;
    }
}];

八、NSArray与字符串

//将NSArray数组中的元素链接成一个字符串
NSArray *arr = @[@"jack",@"rose",@"mark"];
//将每个元素以 # 号拼接
NSString *str = [arr componentsJoinedByString:@"#"];
NSLog(@"%@",str);//jack#rose#mark

//将字符串以某个字符为分隔符存入NSArray数组
NSString *str = @"中国,广州,天河区,棠东";
//以 , 为分隔符存入数组
NSArray *arr = [str componentsSeparatedByString:@","];
//遍历输出数组
for (NSString *obj in arr) {
    NSLog(@"%@",obj);
}
/* 输出
 中国
 广州
 天河区
 棠东
 */

九、NSMutableArray

NSMutableArray是NSArray的子类,所以他具备NSArray的所有特点。唯一区别就是NSMutableArray是一个可变数组,存储在该数组中的元素可以删除,可以动态的新增元素

//初始化NSMutableArray数组
//创建一个没有任何元素的数组,最常用也是这种,因为可变数组可以新增
NSMutableArray *arr1 = [NSMutableArray array];
NSMutableArray *arr2 = [[NSMutableArray alloc] init];
//创建一个有5个元素的数组
NSMutableArray *arr3 = [[NSMutableArray alloc] initWithCapacity:5];
//创建数组的同时调用 类方法 初始化数组的元素
NSMutableArray *arr4 = [NSMutableArray arrayWithObjects:@"哈哈", @"呵呵",nil];
//创建数组的同时调用 对象方法 初始化数组的元素
NSMutableArray *arr5 = [[NSMutableArray alloc] initWithObjects:@"哈哈", @"呵呵",nil];

//NSMutableArray增删改查
//新增元素
[arr1 addObject:@"jack"];
[arr1 addObject:@"rose"];
[arr2 addObject:@"mark"];
[arr2 addObject:@"juli"];

//将arr2添加到arr1数组尾部
[arr1 addObjectsFromArray:arr2];

//在指定位置处插入元素
[arr1 insertObject:@"charu" atIndex:0];

//删除指定下标元素
[arr1 removeObjectAtIndex:1];

//删除指定值的元素
[arr1 removeObject:@"mark"];

//删除指定范围内的指定元素
[arr1 removeObject:@"jack" inRange:NSMakeRange(0, 2)];

//删除最后一个元素
[arr1 removeLastObject];

//删除所有元素
[arr1 removeAllObjects];