Foundation
-
NSString
//1.通过字符串常量创建,字符串对象存储在常量区 NSString *str1 = @""; //2.通过allo init创建,存储在堆区 NSString *str2 = [[NSString alloc] initWithFormat:@""]; //3.通过类工厂方法创建,存储在堆区 NSString *str3 = [NSString stringWithFormat:@""]- 如果是通过字符串常量创建字符串对象,那么如果创建多个对象且值相同,只是局部变量名称不同,多个对象指向同一块存储空间(会先去常量区寻找是否有这个值,如果找到就将这个地址返回给一个局部变量);通过alloc创建的不存在这种情况,只要出现alloc,就会在堆空间开辟空间
- 不同平台的存储方式不一样,不同编译器存储的方式也不一样,mac平台会自动对字符串对象进行优化在堆区的显示是一个对象,但是如果是IOS平台就是两个对象;在xcode6一下并且是iOS平台,那么每次alloc都会创建一个新的对象,如果是Xcode6以上那么多次alloc指向同一块存储空间
- 一般情况下,只要通过alloc获取类工厂方法创建的对象,每次都会在堆内存中开辟一块新的存储空间,但是如果是alloc的initWithString方法除外外,因为这个方法是通过浅copy返回一个字符串对象
- copy分为深拷贝和浅拷贝,如果是深拷贝会创建一个新的对象,如果是浅拷贝不会创建新的对象,而是直接返回被拷贝的对象的地址,和平台无关
- atomically:如果传入YES,字符串写入文件的过程中如果没有写完,那么不会生成文件,如果传入NO,字符串写入文件的过程中如果没有写完,会生成文件
- 文件读取和写入
//读取 NSString *str = [NSString stringWithContentsOfFile:@"文件的绝对路径" encoding:NSSUTF8StringEncoding error:&error] //写入 BOOL flag= [str writeToFile:@"文件绝对路径" atomically:YES encoding:NSSUTF8StringEncoding error:nil] //通过URL来读写,如果加载的资源是本机资源,那么URL中的主机地址可以省略,虽然主机地址可以省略,单文件路径最前面的/不能省略,文件路径最前面的/代表国根路径 NSString *path = @"file://127.0.0.1/文件路径"; NSString *url = [NSURL URLWithString:path]; NSString *str = [NSString stringWithContentsOfURL:url encoding:NSSUTF8StringEncoding error:&error]; [str writeToURL:@"文件绝对路径" atomically:YES encoding:NSSUTF8StringEncoding error:nil]- 如果是通过fileURLWithPath创建URL,那么系统会自动给我传入的字符串添加协议头,所以字符串中不需要在写file://,开发中,如果使用本机资源,创建URL时,建议使用fileURLWithPath,因为url不支持中文,如果URL中包含中文,将无法访问,但是fileURLWithPath可以对URL中包含的中文进行处理
- 如果想URL包含中文,又不通过fileURLWithPath,可以通过stringByAddingPercentEscaspesUsingEncoding进行处理
- 比较字符串
//比较两个字符串的内容 BOOL flag= [str isEqualToString:str2]; //比较两个字符串的地址 flag2 = (str1== str2); //字符串大小,比较 阿斯克码 [str1 compare:str2]; //忽略大小写比较 [str2 caseInsensitiveCompare:str2];- 字符串搜索
//是否以特定字符开头,本质就是从字符串第一个字符开始匹配 [str hasPrefix:@""] //判断是否以什么结尾 [str hasSuffix:@""] //判断是否包含, //只要str包含该字符串,就会返回该字符串在str中的起始位置和长度 //如果不存在,返回的length为0,location返回为NSNotFound [str rangeOfString:@""]- 字符串截取
NSRange range = {6,3}; //位置、长度 NSRange range2 = NSMakeRange(6,3); [str substringWithRange:range]; //rangeOfString 是从左至右开始查找,可以使用options: NSBackwradsSearch 反转查找 //从某个位置开始 [str substringFromIndex:] //从开始到某个位置 [str substringToIndex:]- 字符串替换
[str stringByReplaceingOccrurencesOfString:@"老字段" withString:@"新字段"] //去除首尾空格 NSCharacterSet *set = [NSCharacterSet whitespaceCharacterSet]; NSString *newStr = [str stringByTrimmingCharactersInSet:set]- 字符串和路径
//1.判断是否是绝对路径,判断字符串是否以/开头 BOOL flag = [str isAbsolutePath]; //2.获取文件路径中的最后一个目录,获取路径中最后一个/后的内容 NSString *newStr = [str lastPathComponent]; //3.给路径添加目录,本质是在字符串的末尾加上一个/和指定的内容,注意:如果路径后面已经有了/,那么久不会添加/了,如果路径后面有多个/,那么会自动删除多余的 NSString *newStr = [str stringByAppendingPathComponent:@"xx"]; //4.删除文件路径中的最后一个目录,本质是删除最后一个/和后面的内容 NSString *newStr = [str stringByDeletingLatPathComponent] //5.获取路径中文件的拓展名,本质是从字符串的末尾开始查找,截取第一个.后面的内容 NSString *newStr = [str pathExtension] //6.删除路径中文件的拓展名 NSString *newStr = [str stringByDeletingPathExtension] //6.给文件路径添加一个拓展名 NSString *newStr = [str stringByAppendingPathExtension:@"jpg"]- 字符串转换
//将字符串转为大写 NSString *newStr = [str uppercaseString]; //将字符串转为小写 NSString *newStr = [str lowercaseString]; //将首字母转为大写 NSString *newStr = [str capitalizedString]; //字符串与基本数据类型的转换 NSString *str1 = @"110"; int calue1 = [str1 intValue]; //C语言字符串和OC字符串转换 char *cStr = "dsa"; NSString *str = [NSString stringWithUTF8String:cStr]; //OC字符串转C语言字符串 char *c = [str UTF8String]; -
NSMutalbleString
- NSString是不可变的,里面的文字内容是不能进行修改的,NSMutalbleString是可变的,里面的文字内容可以随时更改
//1.创建空的 NSMutalbleString *STR = [NSMutalbleString string]; //2.字符串添加 NSMutalbleString *str = [NSMutalbleString stringWithFormat:@"123"]; [str appendString:@"456"]; //3.字符串删除 NSRange range = [str rangeOfString:@"50"]; [str deleteCharactersInRange:range]; //4.字符串插入 NSSrange *range2 = [str rangeOfString:@"50"]; [str insertString:@"999" atIndex:range2.location]; //5.字符串替换 [str replaceOccurrencesOfString:@"老数据" withString:@"新数据" options:0 range NSMakeRange(0,str.length)]- OC中的枚举,如果不想使用任何一个的话,就使用0;一般情况下OC方法要求传入一个参数如果没有*,大部分是枚举
- 开发中如果字符串经常发生变化,尽量不使用不可变的字符串
-
NSArray
- 只能存放任意OC对象,并且是由顺序的
- 不能存储非OC对象,如int、float等
- 是不可变的,它里面的内容就是永远是固定的,不能删除里面的元素,也不能添加
//单个元素 NSArrat *array = [NSArray arrayWithObject:@"xxx"]; //多个参数、nil是结束符 NSArrat *array = [NSArray arrayWithObjects:@"xxx",@"kkk",@"ooo",nil];- NSArray遍历
//常规循环 for(int i = 0;i<arr.count;++1){ } //for增强 for(NSObject *obj in arr){ } //使用OC数组的迭代器 //每次调用block都会将当前取出的元素和元素对应的索引传递给我们,obj就是取出的元素,idx是索引,stop控制什么时候停止遍历 [arr enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop){}]- 如果使用OC数组存储对象,可以调用OC数组的方法让数组中所有的元素都执行特定的方法;如果数组中保存的不是相同类型数据,并且没有相同方法,那么会报错
//没有参数 [arr makeObjectsPerformSelector:@selector(say)]; //有一个参数,超出一个参数无法使用 [arr makeObjectsPerformSelector:@selector(sayWithName:) withObject:@"xxx"];- NSArray排序
NSArray *arr = @[@10,@11,@16]; //默认升序,想使用compare方法对数组中元素排序,那么数组中的元素必须是Foundation框架中的对象,也就是说不能是自定义的对象 NSArray *arr2 =[arr sortedArrayUsingSelector:@selectorr(compare:)] //对自定义的数据对象进行排序 NSArray *newArr = [arr sortedArrayWithOptions:NSSortStableusingComparator:@NSComparisonResult(Person *obj1,Person *obj2){ return obj1.age>obj2.age; }]- NSArray和NSString转换
NSString * str = [arr componentsJoinedByString:@"-"]; NSArray *array = [str componentsSeparatedByString:@"-"];- NSArray文件读写
//如果将一个数据写入到文件中之后,本质是写入了一个XML文件 //再iOS开发中一般情况下我们将XML文件的拓展名保存为plist [arr writeToFile:@"/dsadasd/da.text",atomically:YES]; //writeToFile 只能写入数据中保存的元素都是Foundation框架中的类创建的对象,如果保存的是自定义的对象将无法写入 NSArray *arr = [NSArray arrayWithContentsofFile:@"/sadasda/abc.plist"]; -
NSMutableArray
//创建空数组
NSMutableArray *arr = [NSMutableArray arrat];
//添加元素
[arr addObject:@"dsa"];
//将指定数组的元素都取出来,放到arr中,并不是将整个数组作为一个元素添加到arr中
[arr addObjectsFromArray:@[@"das",@"dasdas"]];
//注意:将整个数组作为一个元素添加
[arr addObjects:@[@"sda",@"789"]];
//插入元素
[arr insertObject:@"2sad" atIndex:1];
//插入一组数据,指定需要插入的位置和插入多少个
NSRange range = NSMakeRange(2,2);
NSIndexSet *set = [NSIndexSet indexSetWithIndexsInRange:range];
[arr insertObjects:@[@"2sad",@"ppp"] atIndexs:set];
//删除
[arr removeObjectAtIndex:0];
//替换
[arr replaceobjectAtIndex:1,withObject:@"dsa"];
//获取
[arr objectAtIndex:0];
//注意不能通过@[@"12",@"DSAD"]来直接创建NSMutableArray,如果把一个不可变数组当作一个可变数据来使用,会引发运行时错误
- NSDirectory
//遍历
[dist enumerateKeysAndObjectsUsingBlock:^(id key,id obj,BOOL *stop){
}]
-
NSMutableDirectory:NSDirectory有重复key的话保留第一个,NSMutableDirectory有重复的话保存的是最后一个
-
常用结构体
- CGpoint:表示二维平面上的一个点
- CGSize:表示长宽
- CGRect:表示宽高已经左上角的点的坐标
-
NSNumber
- 将基本数据类型转为对象类型
NSNumber *age1 = [NSNumber numberWithInt:age]; NSNumber *number1 = [NSNumber numberWithDouble:number]; //简写,如果传入的是变量必须写@(),如果传入的是常量()可以省略 NSNumber *nn = @(age)- 将对象类型转为基本数据类型
int value = [age intValue]; -
NSValue
- NSNumber是NSValue的子类,但是NSNumber只能包装数字类型
//1.包装常用结构体 CGPoint point = NSMakePoint(10,20); NSVlaue *value = [NSValue valueWithPoint:point]; NSArray *arr = @[value]; //2.包装自定义结构体 typedef struct{ int age; char *name; }Person; Person *p = {1,"sd"}; //valueWithBytes:接收一个指针,需要传递需要包装的结构体的变量的地址 objCType:需要传递需要包装的数据类型 NSValue *value = [NSValue valueWithBytes:&p,objCType:@encode(Person)]; NSArray *arr = @[value]; Pserson res; [value getValue:&res]; -
NSDate
//当前时间 NSDate *now = [NSDate date]; //获取当前所处的时区 NSTimeZone *zone = [NSTimeZone systemTimeZone]; //获取当前时区喝指定时间的时间差 NSInteger seconds = [zone secondsFromGMTForDate:now]; NSDate *newDate = [now dateByAddingTimeInterval:seconds]; //格式化对象 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; //HH 24小时 hh12小时 Z时区 formatter.dataFormat = @"yyyy年MM月dd日 HH时mm分ss秒" NSString *res = [formatter stringFromDate:now]; //NSString ->NSDate NSDate * = [formatter dateFromString:str]; -
NSCalender
NSDate *now = [NSDate date]; NSCalenar *calendar = [NSCalender currentCalendar]; //获取年 NSDateComponents *cmps = [calendar components:NScalenderUnitYear fromDate:now]; NSLog(@"year= %ld",cmps.year);- 一般情况下如果一个方法接收一个参数,这个参数如果时一个枚举,那么可以通过|符号,连接多个枚举值
- 比较两个时间
NSDateComponents *cmps = [calendar components:NScalenderUnitYear fromDate:now,toDate:date,options:0]; -
NSFileManager
NSFileManager *manager = [NSFileManager defaultManager];
// 可以判断文件
BOOL flag = [manager fileExistsAtPath:@"/Users/LNJ/Desktop/lnj.txt"];
NSLog(@"flag = %i", flag);
// 可以判断文件夹
BOOL dir = NO;
flag = [manager fileExistsAtPath:@"/Users/LNJ/Desktop/未命名文件夹",isDirectory:&dir];
NSLog(@"flag = %i,%i", flag,dir);
- NSFileManager的文件访问
- - (NSDictionary *)attributesOfItemAtPath:(NSString *)path error:(NSError **)error;
- 获得path这个文件\文件夹的属性,通过这个获取到的文件夹的大小不准确,要想实现计算一个文件夹中所有文件的大小必须先拿到所有的文件,然后再获取所有文件的大小,然后再加
NSFileManager *manager = [NSFileManager defaultManager];
NSDictionary *dict = [manager attributesOfItemAtPath:@"/Users/LNJ/Desktop/lnj.txt" error:nil];
NSLog(@"dit = %@", dict);
-
(NSArray *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError **)error;
- 获取文件夹中所有文件,只能获取当前文件夹下所有文件,不能获取子文件夹下的问题
-
- (NSData *)contentsAtPath:(NSString *)path;
- 获得文件内容
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *paths = [manager contentsOfDirectoryAtPath:@"/Users/LNJ/Desktop/" error:nil];
NSLog(@"paths = %@", paths);
- (NSArray *)subpathsAtPath:(NSString *)path; 获取文件夹下所有的文件
- (NSArray *)subpathsOfDirectoryAtPath:(NSString *)path error:(NSError **)error;
- 获取文件夹下所有的文件
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *paths = [manager subpathsAtPath:@"/Users/LNJ/Desktop/"];
NSLog(@"paths = %@", paths);
##4.NSFileManager的文件操作
-
- (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error;
- 拷贝
-
- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error;
- 移动(剪切)
-
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error;
- 删除
-
(BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(NSDictionary *)attributes error:(NSError **)error;
- 创建文件夹(createIntermediates为YES代表自动创建中间的文件夹),不能创建文件
NSFileManager *manager = [NSFileManager defaultManager];
BOOL flag = [manager createDirectoryAtPath:@"/Users/LNJ/Desktop/test" withIntermediateDirectories:YES attributes:nil error:nil];
NSLog(@"flag = %i", flag);
- (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr;
- 创建文件(NSData是用来存储二进制字节数据的),不能创建文件夹
NSString *str = @"lnj";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSFileManager *manager = [NSFileManager defaultManager];
BOOL flag = [manager createFileAtPath:@"/Users/LNJ/Desktop/abc.txt" contents:data attributes:nil];
NSLog(@"flag = %i", flag);
- 集合中对象的内存管理
- 如果将一个对象添加到一个数组中,那么数组会对对象进行一次retain
- 当数组对象释放之后,会给数组中所有的对象发送一条release消息
- 当数组移除一个对象之后,会给这个对象发送一条release消息
Copy
- 作用:利用一个源对象产生一个副本对象
- 使用
- 一个对象可以调用copy或mutableCopy方法来创建一个副本对象
- copy:创建的时不可变副本
- mutableCopy:创建的是可变副本
- 前提:需要遵守NSCopying/NSMutableCopying,实现copyWithZone/copymutableWithZone
- 一般情况下拷贝会生成一个新的对象
- 如果是通过不可变对象巧用了copy,那么不会生成一个新的对象,因为原对象是不能修改的,拷贝出来的对象也是不能修改的,所以不会相互修改,OC为了对内存进行优化,所以不会生成新的对象
- 如果没有生成系的呢对象,我们称之为浅拷贝,本质就是指针拷贝,系统会对原来的对象retain,需要对以前的对象进行release
- 如果生成了新的对象,我们称之为深拷贝,本质就是会创建新的休对象,因为生成了新的对象,所以系统不会对以前的对象进行retain,但是因为生成了新的对象,我们需要对新的对象进行release
- copy和property
- copy的第一个用处:防止外界修改内部的数据 以后字符串属性都使用copy
- copy的第二个用处:可以使用copy保存block,这样可以保住block中使用的外界对象的命,避免以后巧用block时,里面的外界对象已经释放
- block默认在栈中,栈中的block访问到了外界的对象,不会对外界对象进行retain
- block可以通过Block_copy()将block放入堆中,如果这时访问了外界对象,会对外界对象进行一次reatain
- 如果是block使用copy并不是拷贝,而是转移
- 只要给block发送一条release消息,block中是以哦那个的对象也会收到该消息
- 如果对象中的block又用到了对象自己,那么为了避免内存泄漏,应该将对象修饰为——block
自定义实现copy
//1.想让自定义的对象能够被copy只需要遵守NSCopying协议
//2.实现协议中的-(id) copyWithZone:(NSZone *)zone
//3.在方法中创建一个副本对象,然后将当前对象的值赋值给副本并返回
- (id) copyWithZone:(NSZone *)zone
{
//1.创建一个新的对象
Person *p = [[[self clasee ] allocWithZone:zone] init];
p.age - _age;
return p;
}
//如果想让子类在copy时保留子类的属性,那么必须重写copyWithZone方法,在该方法中先调用父类创建副本设置值,然后再设置子类特有的值
//d单例模式下copy的实现
static Tools *_instance = nil;
+(instancetype) allocWithZone:(struce _NSZone *)zone
{
//当前代码再多线程中有问题
if(_instance==nil){
_instance = [[super alloocWithZone:zone]init];
}
return _isntance;
//多线程写法
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
_instance = [[super alloocWithZone:zone]init];
})
return _isntance;
}
- (id) copyWithZone:(NSZone *)zone
{
return instance;
}
//如果在MRC中要使用单例,还需要重写,release(什么都不做),retain(直接返回 _instance),retainCount(固定返回一,为了方便沟通,一般返回很大的值而不是1)方法
- 判断项目是ARC还是MRC
#if __has_feature(objc_arc)
NSLog(@"ARC");
#else
NSLog(@"MRC");
#endif
- 使用宏抽取单例
```objc
#define interfaceSingleton(name) +(instancetype)share##name
#if __has_feature(objc_arc)
// ARC
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
#else
// MRC
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (oneway void)release \
{ \
} \
- (instancetype)retain \
{ \
return _instance; \
} \
- (NSUInteger)retainCount \
{ \
return MAXFLOAT; \
}
#endif