一.字符串
1.创建nsstring基本方式
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
//如何创建字符串对象
/*
通过不同的方式创建字符串,字符串对象储存的位置也不一样
>如果是通过字符串常量创建,那么字符串对象存储在常量区中
>如果是通过alloc initWithFormat/stringWithFormat创建,那么字符串对象存储在堆区中
而且需要注意:
>不同的平台存储的方式也不一样,如果是Mac平台系统会自动对字符串对象进行优化,但是如果是iOS平台就是两个对象
>不同的编译器存储的方式也不一样,如果是Xcode6以下并且是在iOS平台,那么每次alloc都会创建一个新的对象,如果是在Xcode6以上那么alloc多次指向同一块存储空间
*/
//1.通过字符串常量创建
//注意:如果是通过字符串常量创建对象,并且字符串常量的内容一致,那么如果创建多个字符串对象,多个对象指向同一块存储空间
NSString *str1 = @"lnj";
NSString *str11 = @"lnj";
NSLog(@"str1 = %p, str11 = %p", str1 ,str11);
//2.通过alloc init创建
//只要调用alloc就会在堆内存中开辟一块存储空间
NSString *str2 = [[NSString alloc]initWithFormat:@"lmj"];
NSString *str22 = [[NSString alloc]initWithFormat:@"lmj"];
NSLog(@"str2 = %p, str22 = %p", str2, str22);
//3.通过类工厂方法创建/ stringWithFormat
//内部其实就是封装了alloc init
NSString *str3 = [NSString stringWithFormat:@"zs"];
NSString *str33= [NSString stringWithFormat:@"zs"];
/*
注意:一般情况下,只要是通过alloc或者类工厂方法创建的对象,每次都会在堆内存中开辟一块新的存储空间
但是如果是通过alloc的initWithString方法除外,因为这个方法是通过copy返回一个字符串对象给我们
而copy又分为深拷贝和浅拷贝,如果是深拷贝会创建一个新的对象,如果是浅拷贝不会创建一个新的对象,而是直接返回被拷贝的对象的地址给我们
*/
NSString *str4 = [[NSString alloc]initWithString:@"ls"];
NSString *str44 = [[NSString alloc]initWithString:@"ls"];
NSLog(@"str4 = %p, str44 = %p", str4, str44);
return 0;
}
2.字符串读写
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
/*
file: 文件路径,
encoding: 编码英文 iOS-5988-1 中文 GBK GBK2312 , 一般情况填写UTF-8
error: 如果读取错误, 会将错误信息保存到error中 ,如果读取正确, 就没有error = nil
注意: 以后在OC方法中但凡看到XXXofFile的方法, 传递的一定是全路径(绝对路径)
*/
NSString *path = @"/Users/xxx/Desktop/n2186/day17/note/abc.txt";
NSError *error = nil;
// 从文件中读取字符串
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if (error == nil) {
NSLog(@"str = %@", str);
}else
{
// error.code;
// error.description;
NSLog(@"error = %@", [error localizedDescription]);
}
/*
// 将字符串写入到文件中
NSString *str = @"iOS0601";
// atomically 如果传入YES, 字符串写入文件的过程中如果没有写完, 那么不会生成文件
// 如果传入NO, 字符串写入文件的过程中如果没有写完, 会生成文件
NSString *path2 = @"/Users/xxx/Desktop/abc.txt";
BOOL flag = [str writeToFile:path2 atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSLog(@"flag = %i", flag);
*/
return 0;
}
3.文件读写、url编码
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
//1.文件读取
/*
//1.创建URL
//协议头 + 主机地址 + 文件路径
// NSString *path = @"file://192.168.199.199/Users/xxx/Desktop/abc.txt";
// NSString *path = @"http://www.baidu.com";
//注意:如果加载的资源是本机上的资源,那么URL中的主机地址可以省略
//虽然主机地址可以省略,但是需要注意,文件路劲中最前面的/不能省略,文件路径最前面的/代表根路径
// NSString *path = @"file:///Users/xxx/Desktop/abc.txt";
// NSURL *url = [NSURL URLWithString:path];
// NSString *path = @"file:///Users/xxx/Desktop/";
//注意:如果是通过NSURL的fileURLWithPath:方法创建URL,那么系统会自动给我们传入的字符串添加协议头(file://),所以字符串中不需要再写file://
// 注意:开发中一 般情况下,如果是访问本机的资源,创建URL的时候,建议使用fileURLWithPath方法创建
//因为url不支持中文,如果URL中包含中文,那么无法访问;但是如果是通过fileURLWithString方法创建URL,哪怕URL中包含中文也可以进行访问,系统内部会自动对URL中包含的中文进行处理
// NSURL *url = [NSURL fileURLWithPath:path];
NSString *path = @"file:///Users/xxx/Desktop/未命名文件夹/abc.txt";
//如果URL中包含中文,又非不通过fileURLWithPath创建,也可以破
//如果想破就必须在创建URL之前先对字符串中的中文进行处理,进行百分号编码
NSLog(@"处理前:%@", path);
path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"处理后:%@", path);
NSURL *url = [NSURL URLWithString:path];
NSLog(@"url = %@", url);
//2.根据URL加载文件中的字符串
NSString *str = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSLog(@"str = %@", str);
*/
//2.文件写入
NSString *str = @"abc";
// NSString *path = @"file:///Users/xxx/Desktop/未命名文件夹/abc.txt";
// path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// NSURL *url = [NSURL URLWithString:path];
NSString *path = @"/Users/xxx/Desktop/未命名文件夹/abc.txt";
NSURL *url = [NSURL fileURLWithPath:path];
[str writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];
//注意点:如果多次往同一个文件中写入内容,那么后一次的会覆盖前一次的
NSString *str2 = @"xxoo";
[str2 writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];
return 0;
}
4.字符串比较
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
NSString *str1 = @"abc";
NSString *str2 = @"ABC";
/*
// 比较两个字符串的"内容"是否相同
BOOL flag = [str1 isEqualToString:str2];
NSLog(@"flag = %i", flag);
// 下面这个方法, 是比较两个字符串的"地址"是否相同
flag = (str1 == str2);
NSLog(@"flag = %i", flag);
*/
// 比较字符串的大小
// NSOrderedAscending 前面的小于后面的
// NSOrderedSame, 两个字符串相等
// NSOrderedDescending 前面的大于后面的
switch ([str1 compare:str2]) {
case NSOrderedAscending:
NSLog(@"str1小于str2");
break;
case NSOrderedSame:
NSLog(@"str1等于str2");
break;
case NSOrderedDescending:
NSLog(@"str1大于str2");
break;
default:
break;
}
/*
// 忽略大小写进行比较
switch ([str1 caseInsensitiveCompare:str2]) {
case NSOrderedAscending:
NSLog(@"str1小于str2");
break;
case NSOrderedSame:
NSLog(@"str1等于str2");
break;
case NSOrderedDescending:
NSLog(@"str1大于str2");
break;
default:
break;
}
*/
return 0;
}
5.字符串搜索
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
// NSString *str = @"http://www.cocochina.com;
// 1.判断是否以什么开头
/*
// 本质就是从字符串的第一个字符开始匹配, 只要不匹配就返回NO
if ([str hasPrefix:@"http://"]) {
NSLog(@"是一个URL");
}else
{
NSLog(@"不是一个URL");
}
*/
// 2.判断是否以什么结尾
/*
// 本质就是从字符串的最后一个字符开始匹配, 只要不匹配就返回NO
if ([str hasSuffix:@".gif"]) {
NSLog(@"动态图片");
}else{
NSLog(@"不是动态图片");
}
*/
// 3.判断字符串中是否包含某一字符串
/*
NSString *str = @"abcd";
// 只要str中包含该字符串, 那么就会返回该字符串在str中的起始位置以及该字符串的长度
// location从0开始 , length从1开始
// 如果str中没有需要查找的字符串, 那么返回的range的length=0, location = NSNotFound
NSRange range = [str rangeOfString:@"lnj"];
// if (range.location == NSNotFound) {
if (range.length == 0){
NSLog(@"str中没有需要查找的字符串");
}else{
NSLog(@"str中有需要查找的字符串");
NSLog(@"location = %lu, length = %lu", range.location, range.length);
}
*/
return 0;
}
6.字符串截取
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
NSString *str = @"<head>小码哥</head>";
/*
// NSRange : 位置/长度
// NSRange range = {6, 3};
// NSRange range;
// range.location = 6;
// range.length = 3;
// 只要是OC提供的结构体, 一般都可以使用NSMakeXXX来创建
// NSRange range = NSMakeRange(6, 3);
*/
/*
// 1.动态获取截取的起始位置
NSUInteger location = [str rangeOfString:@">"].location + 1;
// 2.动态获取截取的长度
// 注意:rangeOfString是从左至右的开始查找, 只要找到就不找了
// NSUInteger length = [str rangeOfString:@"<" options:NSBackwardsSearch].location - location;
NSUInteger length = [str rangeOfString:@"</"].location - location;
NSLog(@"location = %lu, length = %lu", location, length);
NSRange range = NSMakeRange(location, length);
NSString *newStr = [str substringWithRange:range];
NSLog(@"str = %@", str);
NSLog(@"newStr = %@", newStr);
// NSString *temp = @"abcdefa";
// NSRange range =[temp rangeOfString:@"a" options:NSBackwardsSearch];
// NSLog(@"%lu", range.location);
*/
// 从什么地方开始截取, 一直截取到最后
// NSString *newStr = [str substringFromIndex:6];
// NSLog(@"newStr = %@", newStr);
// 从开头开始截取, 一直截取到什么位置
// NSString *newStr = [str substringToIndex:6];
// NSLog(@"newStr = %@", newStr);
/*
<head>小码哥</head> --> 小码哥</head> --> 小码哥
<head>小码哥</head> --> <head>小码哥 --> 小码哥
*/
NSLog(@"str = %@", str);
NSUInteger location = [str rangeOfString:@">"].location + 1;
NSString *newStr = [str substringFromIndex:location];
NSLog(@"newStr = %@", newStr);
location = [newStr rangeOfString:@"</"].location;
// 改变了指针的指向, 并不是修改了原来的字符串
newStr = [newStr substringToIndex:location];
NSLog(@"newStr = %@", newStr);
return 0;
}
7.字符串替换
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
// 需求: 将&符号替换为/
NSString *str = @"http:&&www.baidu.com&img&ht.gif";
// OccurrencesOfString: 要替换谁
// withString: 用谁替换
NSString *newStr = [str stringByReplacingOccurrencesOfString:@"&" withString:@"/"];
NSLog(@"newStr = %@", newStr);
/*
// 1.去除空格 2.将&替换为/
NSString *str = @" http: &&www. baidu.com &img&ht.gif ";
// 1.去除空格
NSString *newStr = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"newStr = |%@|", newStr);
NSString *newStr2 = [newStr stringByReplacingOccurrencesOfString:@"&" withString:@"/"];
NSLog(@"newStr2 = |%@|", newStr2);
*/
/**
// 3.替换首尾
// NSString *str = @" http:&&www.baidu.com&img&ht.gif ";
NSString *str = @"HTTP://www.baidu.com&img&ht.gif";
// NSCharacterSet *set = [NSCharacterSet whitespaceCharacterSet];
// NSString *newStr = [str stringByTrimmingCharactersInSet:set];
NSCharacterSet *set = [NSCharacterSet uppercaseLetterCharacterSet];
NSString *newStr = [str stringByTrimmingCharactersInSet:set];
NSLog(@"newStr = |%@|", newStr);
*/
return 0;
}
8.字符串与路径
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
NSString *str = @"User/ht/Desktop/abc.txt.jpg";
// 1.判断是否是绝对路径
/*
// 其实本质就是判断字符串是否以/开头
if([str isAbsolutePath])
{
NSLog(@"是绝对路径");
}else{
NSLog(@"不是绝对路径");
}
*/
// 2.获取文件路径中的最后一个目录
// 本质就是获取路径中最后一个/后面的内容
/*
NSString *newStr = [str lastPathComponent];
NSLog(@"%@", newStr);
*/
// 3.删除文件路径中的最后一个目录
/*
// 本质就是删除最后一个/后面的内容, 包括/也会被删除
NSString *newStr = [str stringByDeletingLastPathComponent];
NSLog(@"%@", newStr);
*/
// 4.给文件路径添加一个目录
/*
// 本质就是在字符串的末尾加上一个/ 和指定的内容
// 注意: 如果路径后面已经有了/, 那么就不会添加了
// 如果路径后面有多个/, 那么会自动删除多余的/, 只保留一个
NSString *newStr = [str stringByAppendingPathComponent:@"png"];
NSLog(@"%@", newStr);
*/
// 5.获取路径中文件的扩展名
/*
// 本质就是从字符串的末尾开始查找., 截取第一个.后面的内容
NSString *newStr = [str pathExtension];
NSLog(@"%@", newStr);
*/
// 6.删除路径中文件的扩展名
/*
// 本质就是从字符串的末尾开始查找.,删除第一个.和.后面的内容
NSString *newStr = [str stringByDeletingPathExtension];
NSLog(@"%@", newStr);
*/
// 7.给文件路径添加一个扩展名
// 本质就是在字符串的末尾加上一个.和指定的内容
NSString *newStr = [str stringByAppendingPathExtension:@"jpg"];
NSLog(@"%@", newStr);
return 0;
}
9.字符串转换
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
// NSString *str = @"abc";
// 1.将字符串转换为大写
/*
NSString *newStr = [str uppercaseString];
NSLog(@"%@", newStr);
*/
// 2.将字符串转换为小写
/*
NSString *newStr2 = [newStr lowercaseString];
NSLog(@"%@", newStr2);
// htpp://www.baidu.com/img/abc.GIF;
*/
// 3.将字符串的首字符转换为大写
/*
NSString *newStr = [str capitalizedString];
NSLog(@"%@", newStr);
*/
// 4.字符串与基本数据类型的转换
/*
NSString *str1 = @"110";
NSString *str2 = @"120";
// str1 + str2; // 错误
int value1 = [str1 intValue];
int value2 = [str2 intValue];
NSLog(@"sum = %i", value1 + value2);
// 注意: 如果不是int,double,float,bool,integer,longlong这些类型就不要乱用
NSString *str3 = @"abc";
int value3 = [str3 intValue];
NSLog(@"value3 = %i", value3);
*/
// 5.C语言字符串和OC字符串之间的转换
/*
char *cStr = "abc";
NSString *str = [NSString stringWithUTF8String:cStr];
NSLog(@"str = %@", str);
NSString *newStr = @"cdf";
const char *cStr2 = [newStr UTF8String];
NSLog(@"cStr2 = %s", cStr2);
*/
return 0;
}
10.NSMutableString
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
/*
NSString *str = @"abc"; // 一开始str指向@"abc"对应的内存
str = @"cde"; // 修改了str指针的指向, 让它指向@"cde"对应的内存
NSString *newStr = [str stringByReplacingOccurrencesOfString:@"c" withString:@"X"];
NSLog(@"%@", newStr);
*/
// 创建一个空的字符串
NSMutableString *str = [NSMutableString string];
NSLog(@"修改前: %@", str);
[str appendString:@"lnj"];
NSLog(@"修改后: %@", str);
NSMutableString *strM = [[NSMutableString alloc] init];
// strM = [NSMutableString alloc] initWithFormat:<#(NSString *), ...#>
// strM = [NSMutableString stringWithFormat:<#(NSString *), ...#>]
return 0;
}
11.NSMutableString常用方法
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
NSMutableString *strM = [NSMutableString stringWithFormat:@"www.baidu.com.388"];
// 1.在字符串后面添加/image
/*
[strM appendString:@"/image"];
// [strM appendFormat:@"/age is %i", 10];
NSLog(@"strM = %@", strM);
*/
// 2.删除字符串中的388
/*
// 技巧: 在开发中, 我们经常利用rangeOfString和deleteCharactersInRange方法配合起来删除指定的字符串
// 2.1先查找出388在字符串中的位置
NSRange range = [strM rangeOfString:@"388"];
// 2.2删除388
[strM deleteCharactersInRange:range];
NSLog(@"strM = %@", strM);
*/
// 3.在388前面插入love这个单词
/*
// insertString : 需要插入的字符串
// atIndex: 从哪里开始插入
NSRange range = [strM rangeOfString:@"388"];
[strM insertString:@"love" atIndex:range.location];
NSLog(@"strM = %@", strM);
*/
// 4.要求将字符串中的388替换为530
// 注意: 如果是调用NSString的字符串替换方法, 不会修改原有字符串, 而是生成一个新的字符串
// NSString *newStr =[strM stringByReplacingOccurrencesOfString:@"388" withString:@"530"];
// 注意: 一般情况下OC方法要求传入一个参数如果没有*, 大部分都是枚举
// 一般情况下如果不想使用枚举的值, 可以传入0, 代表按照系统默认的方式处理
// OccurrencesOfString: 需要替换的字符串
// withString: 用什么替换
// options: 替换时的搜索方式
// range: 搜索的范围
// 返回值: 代表替换了多少个字符串
NSUInteger count = [strM replaceOccurrencesOfString:@"388" withString:@"530" options:0 range:NSMakeRange(0, strM.length)];
NSLog(@"strM = %@", strM);
NSLog(@"count = %lu", count);
// NSLog(@"newStr = %@", newStr);
return 0;
}
二、数组
1.nsarray
NSArray
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
/*
// NSArray *arr = [[NSArray alloc] init];
// NSArray *arr = [NSArray arrayWithObject:@"a"];
// 数组中的nil是结束符
NSArray *arr = [NSArray arrayWithObjects:@"la", @"lb" ,@"jjj", @"cp", nil];
NSLog(@"%@", arr);
*/
/*
Person *p = [Person new];
NSObject *obj = [NSObject new];
NSArray *arr = [NSArray arrayWithObjects:p, obj, @"lnj", nil];
NSLog(@"arr = %@", arr);
NSLog(@"count = %lu", [arr count]);
NSLog(@"last = %@", [arr lastObject]);
NSLog(@"first = %@", [arr firstObject]);
NSLog(@"arr[1] = %@", [arr objectAtIndex:1]);
*/
/*
NSArray *arr = [NSArray arrayWithObjects:@"la", @"lb", @"jjj", @"zs", nil];
if([arr containsObject:@"zs"])
{
NSLog(@"arr中包含zs");
}else
{
NSLog(@"arr中不包含zs");
}
*/
// 创建数组简写
NSString *str = @"la";
// NSArray *arr = [NSArray arrayWithObjects:@"laj", @"lbj", @"jjj", nil];
NSArray *arr = @[@"aj", @"lbj", @"jjj"];
// 获取数组元素的简写
NSLog(@"%@", [arr objectAtIndex:0]);
NSLog(@"%@", arr[0]);
return 0;
}
2.nsarray遍历
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
// NSArray *arr = @[@"a", @"la", @"jjj"];
/*
// 常规遍历
for (int i = 0; i < arr.count; ++i) {
NSLog(@"arr[%i] = %@", i, arr[i]);
}
*/
// 如果是OC数组可以使用OC中的增强for循环来遍历
// 逐个取出arr中的元素, 将取出的元素赋值给obj
// 注意: obj的类型可以根据数组中元素的类型来写, 不一定要写NSObject
// for (NSString *obj in arr) {
// NSLog(@"obj = %@", obj);
// }
/*
// 使用OC数组的迭代器来遍历
// 每取出一个元素就会调用一次block
// 每次调用block都会将当前取出的元素和元素对应的索引传递给我们
// obj就是当前取出的元素, idx就是当前元素对应的索引
// stop用于控制什么时候停止遍历
[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx == 1) {
*stop = YES;
}
NSLog(@"obj = %@, idx = %lu", obj, idx);
}];
*/
Person *p1 = [Person new];
Person *p2 = [Person new];
Person *p3 = [Person new];
Person *p4 = [Person new];
NSArray *arr = @[p1, p2, p3, p4];
/*
[arr enumerateObjectsUsingBlock:^(Person *obj, NSUInteger idx, BOOL *stop) {
[obj say];
}];
*/
// 如果使用OC数组存储对象, 可以调用OC数组的方法让数组中所有的元素都执行指定的方法
// 注意点: 如果数组中保存的不是相同类型的数据, 并且没有相同的方法, 那么会报错
// [arr makeObjectsPerformSelector:@selector(say)];
// withObject: 需要传递给调用方法的参数
[arr makeObjectsPerformSelector:@selector(sayWithName:) withObject:@"lnj"];
return 0;
}
3.nsarray排序
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
/*
NSArray *arr = @[@10, @20, @5, @7, @15];
NSLog(@"排序前: %@", arr);
// 注意: 想使用compare方法对数组中的元素进行排序, 那么数组中的元素必须是Foundation框架中的对象, 也就是说不能是自定义对象
NSArray *newArr = [arr sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"排序后: %@", newArr);
*/
Person *p1 = [Person new];
p1.age = 10;
Person *p2 = [Person new];
p2.age = 20;
Person *p3 = [Person new];
p3.age = 5;
Person *p4 = [Person new];
p4.age = 7;
NSArray *arr = @[p1, p2, p3, p4];
NSLog(@"排序前: %@", arr);
// 按照人的年龄进行排序
// 不能使用compare:方法对自定义对象进行排序
// NSArray *newArr = [arr sortedArrayUsingSelector:@selector(compare:)];
// 该方法默认会按照升序排序
NSArray *newArr = [arr sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult(Person *obj1, Person *obj2) {
// 每次调用该block都会取出数组中的两个元素给我们
// 二分
// NSLog(@"obj1 = %@, obj2 = %@", obj1, obj2);
return obj1.age > obj2.age;
// return obj1.age < obj2.age;
/*
if (obj1.age > obj2.age) {
// 5 4
return NSOrderedDescending;
}else if(obj1.age < obj2.age)
{
// 4 5
return NSOrderedAscending;
}else
{
return NSOrderedSame;
}
*/
}];
NSLog(@"排序后: %@", newArr);
return 0;
}
4.nsstring和nsarray之间转换
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
NSArray *arr = @[@"lj", @"j", @"jjj"];
// 需求: 用-将所有的姓名连接起来生成一个字符串
// 1.定义一个可变字符串保存拼接之后的结果
NSMutableString *strM = [NSMutableString string];
// 2.遍历数组, 取出数组中的每一个元素, 将元素添加到可变字符串中
for (NSString *str in arr) {
[strM appendString:str];
// 3.每次添加完毕之后再添加一个-
[strM appendString:@"-"];
}
NSLog(@"strM = %@", strM);
[strM deleteCharactersInRange:NSMakeRange(strM.length - 1, 1)];
NSLog(@"strM = %@", strM);
/*
NSString *str = [arr componentsJoinedByString:@"**"];
NSLog(@"str = %@", str);
*/
/*
// 通过一个字符串生成一个数组
// 也叫做字符串切割
NSString *str = @"l*m*jjj";
NSArray *arr = [str componentsSeparatedByString:@"*"];
NSLog(@"arr = %@", arr);
*/
return 0;
}
5.nsarray读写
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
// 1.将数组写入到文件中
/*
NSArray *arr = @[@"l", @"j", @"jjj"];
// 其实如果将一个数组写入到文件中之后, 本质是写入了一个XML文件
// 在iOS开发中一般情况下我们会将XML文件的扩展名保存为plist
BOOL flag = [arr writeToFile:@"/Users/qinlong/Downloads/已经归档分类的/公司项目/abc.plist" atomically:YES];
NSLog(@"flag = %i", flag);
*/
Person *p1 = [Person new];
p1.age = 10;
Person *p2 = [Person new];
p2.age = 20;
Person *p3 = [Person new];
p3.age = 5;
Person *p4 = [Person new];
p4.age = 7;
NSArray *arr = @[p1, p2, p3, p4];
// 注意:writeToFile只能写入数组中保存的元素都是Foundation框架中的类创建的对象, 如果保存的是自定义对象那么不能写入
BOOL flag = [arr writeToFile:@"/Users/qinlong/Downloads/已经归档分类的/公司项目person.plist" atomically:YES];
NSLog(@"flag = %i", flag);
// 2.从文件中读取一个数组
/*
NSArray *newArray = [NSArray arrayWithContentsOfFile:@"/Users/xiaomage/Desktop/abc.plist"];
NSLog(@"%@", newArray);
*/
return 0;
}
6.nsmutablearray
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
// 创建一个空的数组
NSMutableArray *arrM = [NSMutableArray array];
NSLog(@"%@", arrM);
// 如何添加
[arrM addObject:@"lnj"];
// 将指定数组中的元素都取出来, 放到arrM中
// 并不是将整个数组作为一个元素添加到arrM中
[arrM addObjectsFromArray:@[@"l", @"jjj"]];
// 注意: 以下是将整个数组作为一个元素添加
// [arrM addObject:@[@"l", @"jjj"]];
NSLog(@"%@", arrM);
// 如何插入
[arrM insertObject:@"xcq" atIndex:1];
NSLog(@"%@", arrM);
NSRange range = NSMakeRange(2, 2);
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:range];
// 插入一组数据, 指定数组需要插入的位置, 和插入多少个
[arrM insertObjects:@[@"A", @"B"] atIndexes:set];
NSLog(@"%@", arrM);
/*
// 如何删除
[arrM removeObjectAtIndex:0];
NSLog(@"%@", arrM);
[arrM removeLastObject];
NSLog(@"%@", arrM);
[arrM removeObject:@"A"];
NSLog(@"%@", arrM);
// 如何替换
[arrM replaceObjectAtIndex:1 withObject:@"M"];
NSLog(@"%@", arrM);
// 如何获取
NSLog(@"%@", [arrM objectAtIndex:0]);
NSLog(@"%@", arrM[0]);
// 替换
arrM[0] = @"ZS";
NSLog(@"%@", arrM);
// 注意: 不能通过@[]来创建一个可变数组, 因为@[]创建出来的是一个不可变的数组
// 如果把一个不可变数组当做一个可变数组来使用, 会引发一个运行时的错误
NSMutableArray *arrM = @[@"l", @"j"];
[arrM addObject:@"JJJ"];*/
return 0;
}
三.字典
1.nsdictionary
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
// 1.如何创建
// NSDictionary *dict = [NSDictionary dictionaryWithObject:@"lnj" forKey:@"name"];
// NSString *name = [dict objectForKey:@"name"];
// NSLog(@"name = %@", name);
// 注意: key和value 是一一对应
// NSDictionary *dict = [NSDictionary dictionaryWithObjects:@[@"l", @"300", @"1.75"] forKeys:@[@"name", @"age", @"height"]];
// NSLog(@"%@ %@ %@", [dict objectForKey:@"name"], [dict objectForKey:@"age"], [dict objectForKey:@"height"]);
// NSDictionary *dict = @{key:value};
// NSDictionary *dict = @{@"name": @"lnj"};
// NSLog(@"%@", dict[@"name"]);
// NSDictionary *dict = @{@"name":@"l", @"age":@"300", @"height":@"1.75"};
// NSLog(@"%@ %@ %@", dict[@"name"], dict[@"age"], dict[@"height"]);
// 2.字典的遍历
// NSDictionary *dict = @{@"name":@"l", @"age":@"300", @"height":@"1.75"};
// 2.1如何获取字典中key和value的个数, 在字典中key称之为键, value称之为值
// NSLog(@"count = %lu", [dict count]);
/*
for (int i = 0; i < dict.count; ++i) {
// 获取字典中所有的key
NSArray *keys = [dict allKeys];
// 取出当前位置对应的key
// NSLog(@"%@", keys[i]);
NSString *key = keys[i];
NSString *value = dict[key];
NSLog(@"key = %@, value = %@", key, value);
}
*/
/*
// 如何通过forin遍历字典, 会将所有的key赋值给前面的obj
for (NSString *key in dict) {
// NSLog(@"%@", key);
NSString *value = dict[key];
NSLog(@"key = %@, value = %@", key, value);
}
*/
/*
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(@"key = %@, value = %@", key, obj);
}];
*/
// 3.字典文件读写
NSDictionary *dict = @{@"name":@"l", @"age":@"300", @"height":@"1.75"};
// XML 扩展名plist
[dict writeToFile:@"/Users/qinlong/Downloads/已经归档分类的/公司项目/info.plist" atomically:YES];
// 注意: 字典和数组不同, 字典中保存的数据是无序的
NSDictionary *newDict = [NSDictionary dictionaryWithContentsOfFile:@"/Users/xiaomage/Desktop/info.plist"];
NSLog(@"%@", newDict);
NSArray *arr = @[@10, @20, @30, @5];
[arr writeToFile:@"/Users/qinlong/Downloads/已经归档分类的/公司项目/abc.plist" atomically:YES];
return 0;
}
2.nsmutabledictionary
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
/*
// 1.创建一个空的字典
NSMutableDictionary *dictM = [NSMutableDictionary dictionary];
NSLog(@"%@", dictM);
// 2.如何添加
[dictM setObject:@"l" forKey:@"name"];
NSLog(@"%@", dictM);
// 会将传入字典中所有的键值对取出来添加到dictM中
[dictM setValuesForKeysWithDictionary:@{@"age":@"300", @"height":@"1.75"}];
NSLog(@"%@", dictM);
// 3.如何获取
NSLog(@"name = %@", dictM[@"name"]);
// 4.如何删除
[dictM removeObjectForKey:@"name"];
NSLog(@"%@", dictM);
// [dictM removeObjectsForKeys:@[@"age", @"height"]];
// NSLog(@"%@", dictM);
// 5.如何修改
// 如果利用setObject方法给同名的key赋值, 那么新值会覆盖旧值
// [dictM setObject:@"88" forKey:@"age"];
dictM[@"age"] = @"88";
NSLog(@"%@", dictM);
*/
// 1.不能使用@{}来创建一个可变的字典
// NSMutableDictionary *dictM = @{@"name":@"l"};
// [dictM setObject:@"30" forKey:@"age"];
// 2.如果是不可变数组, 那么key不能相同
// 如果是不可变字典出现了同名的key, 那么后面的key对应的值不会被保存
// 如果是在可变数组中, 后面的会覆盖前面的
NSDictionary *dict = @{@"name":@"l", @"name":@"j"};
NSLog(@"dict = %@", dict);
NSMutableDictionary *dictM = [NSMutableDictionary dictionaryWithObjects:@[@"lj", @"j"] forKeys:@[@"name", @"name"]];
NSLog(@"dict = %@", dictM);
return 0;
}
四.nsnumber
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
int age = 10;
double number= 5.1;
int value = 6;
// NSArray *arr = @[age, number, value];
// 1.将基本数据类型转换为对象类型
NSNumber *ageN = [NSNumber numberWithInt:age];
NSNumber *numberN = [NSNumber numberWithDouble:number];
NSNumber *valueN = [NSNumber numberWithInt:value];
NSArray *arr = @[ageN, numberN, valueN];
NSLog(@"arr = %@", arr);
// 2.将对象类型转换为基本数据类型
// int temp = [ageN intValue];
// double temp = [numberN doubleValue];
// NSLog(@"%f", temp);
// 3.基本数据类型转换对象类型简写
// 注意: 如果传入的是变量那么必须在@后面写上(), 如果传入的常量, 那么@后面的()可以省略
// NSNumber *temp = @(number);
NSNumber *temp =@10.10;
NSLog(@"%@", temp);
return 0;
}
<h2>五.nsvalue</h2>
</pre><pre code_snippet_id="1702228" snippet_file_name="blog_20160604_21_9228691" name="code" class="objc">
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
/*
typedef struct{
int age;
char *name;
double _height;
}Person;
Person p = {300, "l", 1.75};
// NSArray *arr = @[p];
*/
// 1.利用NSValue包装常用的结构体
/*
CGPoint point = NSMakePoint(10, 20);
NSValue *value = [NSValue valueWithPoint:point];
NSArray *arr = @[value];
NSLog(@"%@", arr);
*/
// 2.利用NSValue包装自定义的结构体
typedef struct{
int age;
char *name;
double height;
}Person;
Person p = {300, "j", 1.75};
// valueWithBytes: 接收一个指针, 需要传递需要包装的结构体的变量的地址
// objCType: 需要传递需要包装的数据类型
NSValue *pValue = [NSValue valueWithBytes:&p objCType:@encode(Person)];
NSArray *arr = @[pValue];
NSLog(@"%@", arr);
// 从NSValue中取出自定义的结构体变量
Person res;
[pValue getValue:&res];
NSLog(@"age = %i, name = %s, height = %f", res.age, res.name, res.height);
return 0;
}
六.NSCalendar
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
// 1.获取当前时间的年月日时分秒
/*
// 获取当前时间
NSDate *now = [NSDate date];
NSLog(@"now = %@", now);
// 日历
NSCalendar *calendar1 = [NSCalendar currentCalendar];
// 利用日历类从当前时间对象中获取 年月日时分秒(单独获取出来)
// components: 参数的含义是, 问你需要获取什么?
// 一般情况下如果一个方法接收一个参数, 这个参数是是一个枚举 , 那么可以通过|符号, 连接多个枚举值
NSCalendarUnit type = NSCalendarUnitYear |
NSCalendarUnitMonth |
NSCalendarUnitDay |
NSCalendarUnitHour |
NSCalendarUnitMinute |
NSCalendarUnitSecond;
NSDateComponents *cmps = [calendar1 components:type fromDate:now];
NSLog(@"year = %ld", cmps.year);
NSLog(@"month = %ld", cmps.month);
NSLog(@"day = %ld", cmps.day);
NSLog(@"hour = %ld", cmps.hour);
NSLog(@"minute = %ld", cmps.minute);
NSLog(@"second = %ld", cmps.second);
*/
// 2.比较两个时间之间的差值, 比较相差多少年多少月多少日多少小时多少分钟多少秒
// 2.1过去的一个时间
NSString *str = @"2015-06-29 07:05:26 +0000";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss Z";
NSDate *date = [formatter dateFromString:str];
// 2.2当前的时间
NSDate *now = [NSDate date];
NSLog(@"date = %@", date);
NSLog(@"now = %@", now);
// 2.3比较两个时间
NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit type = NSCalendarUnitYear |
NSCalendarUnitMonth |
NSCalendarUnitDay |
NSCalendarUnitHour |
NSCalendarUnitMinute |
NSCalendarUnitSecond;
NSDateComponents *cmps = [calendar components:type fromDate:date toDate:now options:0];
NSLog(@"%ld年%ld月%ld日%ld小时%ld分钟%ld秒钟", cmps.year, cmps.month, cmps.day, cmps.hour, cmps.minute, cmps.second);
return 0;
}
七.NSFileManager
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
NSFileManager *manager = [NSFileManager defaultManager];
// 1.判断一个文件或者文件夹是否存在
/*
BOOL flag = [manager fileExistsAtPath:@"/Users/Desktop/video/01.mp4"];
NSLog(@"flag = %i", flag);
*/
// 2.判断一个文件是否存在, 并且判断它是否是一个文件夹
/*
// 注意: 该方法的返回值是说明传入的路径对应的文件或文件夹是否存在
// 第二个参数是用于保存判断结果的, 如果是一个目录, 那么就会赋值为YES, 如果不是就赋值为NO
BOOL dir = NO;
BOOL flag = [manager fileExistsAtPath:@"/Users/Desktop/video/01-NSArray基本概念.mp4" isDirectory:&dir];
NSLog(@"flag = %i, dir = %i", flag, dir);
*/
// 3.获取文件或文件夹的属性
/*
NSDictionary *info = [manager attributesOfItemAtPath:@"/Users/Desktop/video/01-NSArray基本概念.mp4" error:nil];
NSLog(@"info = %@", info);
*/
// 4.获取文件夹中所有的文件
/*
// 注意:contentsOfDirectoryAtPath方法有一个弊端, 只能获取当前文件夹下所有的文件, 不能获取子文件夹下面的文件
NSArray *res = [manager contentsOfDirectoryAtPath:@"/Users/Desktop/video" error:nil];
NSLog(@"res = %@", res);
*/
/*
// NSArray *res = [manager subpathsAtPath:@"/Users/xiaomage/Desktop/video"];
NSArray *res = [manager subpathsOfDirectoryAtPath:@"/Users/Desktop/video" error:nil];
NSLog(@"res = %@", res);
// 作业: 要求计算一个文件夹中所有文件的大小
// 注意: 如果通过attributesOfItemAtPath方法直接获取, 那么获取到的文件夹的大小不准确
// 要想实现计算一个文件夹中所有文件的大小必须先拿到所有的文件, 然后再获取所有文件的大小, 然后再相加
*/
// 5.创建文件夹
/*
// createDirectoryAtPath: 告诉系统文件夹需要创建到什么位置
// withIntermediateDirectories: 如果指定的文件中有一些文件夹不存在, 是否自动创建不存在的文件夹
// attributes: 指定创建出来的文件夹的属性
// error: 是否创建成功, 如果失败会给传入的参数赋值
// 注意: 该方法只能用于创建文件夹, 不能用于创建文件
BOOL flag = [manager createDirectoryAtPath:@"/Users/qinlong/Downloads/已经归档分类的/公司项目/abc" withIntermediateDirectories:YES attributes:nil error:nil];
NSLog(@"%i", flag);
*/
// 6.创建文件
// createFileAtPath: 指定文件创建出来的位置
// contents : 文件中的内容
// attributes: 创建出来的文件的属性
// NSData : 二进制数据
// 注意: 该方法只能用于创建文件, 不能用于创建文件夹
NSString *str = @"啊哈真帅";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
[manager createFileAtPath:@"/Users/qinlong/Downloads/已经归档分类的/公司项目/abc.txt" contents:data attributes:nil];
return 0;
}
八.copy
1.基本使用
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
/*
// 会生成一个新的对象
NSString *srcStr = @"abc";
// 只要是拷贝出来的对象, 拷贝出来的对象中的内容和以前对象中的内容一致
// "一般"情况下拷贝会生成一个新的对象
// 为什么会产生一个新的对象 1.因为拷贝要求修改原来的对象不能影响到拷贝出来得对象 \
修改拷贝出来的对象也不能影响到原来的对象, 所以需要生成一个新的对象 \
2.由于以前的对象是一个不可变的对象, 而通过mutableCopy拷贝出来的对象必须是一个可变的对象, 所以必须生成一个新的对象
NSMutableString *copyStr = [srcStr mutableCopy];
NSLog(@"srcStr = %@, copyStr = %@", srcStr, copyStr);
NSLog(@"srcStr = %p, copyStr = %p", srcStr, copyStr);
*/
/*
// 会生成一个新的对象
NSMutableString *srcStr = [NSMutableString stringWithFormat:@"labc"];
NSMutableString *copyStr = [srcStr mutableCopy];
[srcStr appendString:@" cool"];
NSLog(@"srcStr = %@, copyStr = %@", srcStr, copyStr);
NSLog(@"srcStr = %p, copyStr = %p", srcStr, copyStr);
*/
// 会生成一个新的对象
/**
NSMutableString *srcStr = [NSMutableString stringWithFormat:@"abc"];
NSString *copyStr = [srcStr copy];
[srcStr appendString:@" cool"];
NSLog(@"srcStr = %@, copyStr = %@", srcStr, copyStr);
NSLog(@"srcStr = %p, copyStr = %p", srcStr, copyStr);
*/
//不会生成新对象
// 如果是通过不可变对象调用了copy方法, 那么不会生成一个新的对象
// 原因: 因为原来的对象是不能修改的, 拷贝出来的对象也是不能修改的
// 既然两个都不能修改, 所以永远不能影响到另外一个对象, 那么已经符合需求
// 所以: OC为了对内存进行优化, 就不会生成一个新的对象
/**
NSString *srcStr = @"lccj";
NSString *copyStr = [srcStr copy];
NSLog(@"srcStr = %p, copyStr = %p", srcStr, copyStr);
*/
/*
正是因为调用copy方法有时候会生成一个新的对象, 有时候不会生成一个新的对象
所以: 如果没有生成新的对象, 我们称之为浅拷贝, 本质就是指针拷贝
如果生成了新的对象, 我们称之为深拷贝, 本质就是会创建一个新的对象
*/
return 0;
}
2.内存管理
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
#pragma mark 在MRC环境下内存管理
/*
//NSString *str1 = @"abc";
char *cstr = "this is a c string";
NSString *str1 = [[NSString alloc] initWithUTF8String:cstr];
NSLog(@"str = %lu", [str1 retainCount]); // 1
// 不会产生新对象, 会对原有对象进行一次retain
NSString *str2 = [str1 copy]; // 2
NSLog(@"str = %lu", [str1 retainCount]);
// 注意点: 如果是浅拷贝, 那么会对拷贝的对象进行一次retain, 那么我们就需要对拷贝出来的对象进行一次release 如果是深拷贝则只会产生一个新对象
[str2 release]; // 1
[str1 release]; // 0
*/
char *cstr = "this is a c string";
NSString *str1 = [[NSString alloc] initWithUTF8String:cstr];
NSLog(@"str1 = %lu", [str1 retainCount]); // 1
// 会生成一个新的对象
NSMutableString *str2 = [str1 mutableCopy];
NSLog(@"%p %p", str1, str2);
NSLog(@"str2 = %lu", [str2 retainCount]); // 1
[str1 release];
[str2 release];
/*
内存管理的原则, 有加就有减
一次alloc/retain/copy 对应一次release
*/
}
return 0;
}
3.Copy与Property
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
int main(int argc, const char * argv[]) {
// 1.copy的第一个用途, 防止外界修改对象内部的数据
/*
NSMutableString *temp = [NSMutableString stringWithFormat:@"sbc"];
Person *p = [[Person alloc] init];
p.name = temp; //把temp指针赋值给了name (此时 temp 和 name 都指向同一块内存空间)
// 问题: 修改了外面的变量, 影响到了对象中的属性
[temp appendString:@" cool"];
NSLog(@"name = %@", p.name); //打印结果: sbc cool
// 记住: 以后字符串属性都用copy
*/
/*
__block int num = 10;
void (^myBlock)() = ^{
num = 20;
NSLog(@"%i", num);
};
myBlock();
*/
/*
// block默认存储在栈中, 栈中的block访问到了外界的对象, 不会对对象进行retain
// block如果在堆中, 如果在block中访问了外界的对象, 会对外界的对象进行一次retain
Person *p = [[Person alloc] init];
NSLog(@"retainCount = %lu", [p retainCount]);
void (^myBlock)() = ^{
NSLog(@"%@", p);
NSLog(@"retainCount = %lu", [p retainCount]);
};
Block_copy(myBlock); // 将block转移到堆中
myBlock();
*/
// 2.可以使用copy保存block到堆中, 这样可以保住block中使用的外界对象的命
/*
// 避免以后调用block的时候, 外界的对象已经释放了
Dog *d = [[Dog alloc] init]; // 1
NSLog(@"retainCount = %lu", [d retainCount]);
Person *p = [[Person alloc] init];
p.pBlock = ^{
// 2
NSLog(@"%@", d);
};
NSLog(@"retainCount = %lu", [d retainCount]); // 2
// 如果狗在调用block之前释放了, 那么程序就会崩溃
[d release]; // 1
p.pBlock();
[p release];
*/
// 3.注意点: copy block之后引发循环引用
// 如果对象中的block又用到了对象自己, 那么为了避免内存泄露, 应该将对象修饰为__block
__block Person *p = [[Person alloc] init]; // 1
p.name = @"lnj";
NSLog(@"retainCount = %lu", [p retainCount]);
p.pBlock = ^{
NSLog(@"name = %@", p.name); // 2
};
NSLog(@"retainCount = %lu", [p retainCount]);
p.pBlock();
[p release]; // 1
// [p release]; // 2B
return 0;
}