------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1. NSFileManager
1) 简介
① 使用来管理文件系统的,它可以用来进行常见的文件/文件夹操作(拷贝、剪切、创建等)。
② NSFileManager使用了单例模式(singleton),使用defaultManager法可以获取那个单利对象,[NSFileManager defaultManager]
2) NSFileManager 用于判断
首先要创建文件管理对象,调用defaultManager方法创建一个文件管理的单例对象。
单例对象:在程序运行期间,只有一个对象存在
NSFileManager *fm = [NSFileManagerdefaultManager];
//创建路径对象
NSString *filePath =@"/Users/mac/Desktop/dict.plist";
NSString *filePath2 =@"/Users/mac/Desktop";
//判断路径是否存在
BOOL isYES = [fm fileExistsAtPath:filePath];
NSLog(@"isYES =%d",isYES); //1
isYES = [fm fileExistsAtPath:filePath2];
NSLog(@"isYES = %d",isYES); //1
//判断是否是一个目录
[fm fileExistsAtPath:filePath isDirectory:&isYES];
NSLog(@"isYES = %d",isYES); //0
[fmfileExistsAtPath:filePath2 isDirectory:&isYES];
NSLog(@"isYES = %d",isYES); //1
//判断是否可读
isYES = [fm isReadableFileAtPath:filePath];
NSLog(@"isYES = %d",isYES); //1
isYES = [fm isReadableFileAtPath:filePath2];
NSLog(@"isYES = %d",isYES); //1
//判断是否可写
isYES = [fm isWritableFileAtPath:filePath];
NSLog(@"isYES = %d",isYES); //1
isYES = [fm isWritableFileAtPath:filePath2];
NSLog(@"isYES = %d",isYES); //1
//判断是否可删除
isYES = [fm isDeletableFileAtPath:filePath];
NSLog(@"isYES = %d",isYES); //1
isYES = [fm isDeletableFileAtPath:filePath2];
NSLog(@"isYES = %d",isYES); //1
3) NSFileManager的文件访问
//创建文件对象和路径
NSFileManager *fm =[NSFileManager defaultManager];
NSString *filePath = @"/Users/mac/Desktop";
//①获取文件属性信息
NSDictionary *dict = [fm attributesOfItemAtPath:filePath error:nil];
NSLog(@"dict = %@",dict);
//②获取某个目录及其子目录的内容
//a.递归方法(效率相对低)
NSArray *subPaths = [fm subpathsAtPath:filePath];
NSLog(@"subPaths = %@",subPaths);
//b.非递归方法(效率高)
subPaths = [fm subpathsOfDirectoryAtPath:filePath error:nil];
NSLog(@"subPaths = %@",subPaths);
//③获取当前目录下的内容(不包括子目录)
subPaths = [fmcontentsOfDirectoryAtPath:filePath error:nil];
NSLog(@"subPaths =%@",subPaths);
4) //文件操作
//创建文件管理对象
NSFileManager *fm = [NSFileManager defaultManager];
//创建目录
//先指定一个路径
NSString *filePath = @"/Users/mac/Desktop/aaa";
BOOL isSuccess = [fm createDirectoryAtPath:filePathwithIntermediateDirectories:YES attributes:nil error:nil];
//参数1:指定要创建的目录;参数2:创建的时候,YES表示如果缺少其他目录,会自动创建,NO表示不会创建;参数3:属性字典;参数4:错误对象。
if(isSuccess){
NSLog(@"创建成功!");
}
//创建文件
//先指定文件路径
NSString *aPath = @"/Users/mac/Desktop/aaa/a.txt";
NSString *str = @"我参加了中国好声音,落选了。";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
BOOL isOK = [fm createFileAtPath:aPath contents:data attributes:nil];
//参数1:创建的文件所在路径;参数2:文件内容,NSData类型数据;参数3:文件属性字典;
//NSData:处理二进制数据的类
if(isOK){
NSLog(@"创建成功!");
}
//copy文件
NSString *toPath = @"/Users/mac/Desktop/bbb/";
[fm copyItemAtPath:aPath toPath:toPath error:nil];
//移动文件
[fm moveItemAtPath:aPath toPath:toPath error:nil];
//删除文件
[fm removeItemAtPath:aPath error:nil];
2. NSFileManager文件下载思路
1) 发送请求给服务器,要求下载某个文件
2) 服务器发出响应,返回文件数据
3) 手机客户端利用NSData来存放服务器返回的文件数据
4) 利用NSFileManager将NSData里面的文件数据写到新的文件中。
3. iOS沙盒机制
1) 每个iOS应用都有自己的应用沙盒,应用沙盒就是文件系统目录,与其他应用的文件系统隔离,iOS系统不允许访问其他应用的应用沙盒。在iOS8中已经开放访问(extension)。
2) 应用沙盒一般包括的文件目录为:应用程序包、Documents、Library(下面有Caches和Perferences目录)、tmp.
应用程序包:包含所有的资源文件和可执行文件
Documents:保存应用运行时生成的需要持久化的数据,iTunes会自动备份该目录。苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录。
tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也有可能会清除该目录下的文件,iTunes不会同步该目录。iPhone重启时,该目录下的文件会丢失。
Library:存储程序的默认位置和其他状态信息,iTunes会自动备份该目录。
Library/Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出后删除。一般存放体积比较大,不是特别重要的资源。
Library/Preferences:保存应用的所有偏好设置,iOS的settings应用会在该目录中查找应用的设置信息,iTunes会自动备份该目录。
3) 沙盒路径获取
//沙盒各个路径的获取
//①获取沙盒路径
//mac下是用户的根目录
//iOS中是沙盒根目录
NSString *sandBoxPath = NSHomeDirectory();
//②Documents路径
NSArray *documentsArr =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsStr = [documentsArr objectAtIndex:0];
//NSSearchPathForDirectoriesInDomains 返回绝对路径
//参数1:要查找的目录;参数2:是否是用户主目录;参数3:是否获取全路径
//NSDocumentDirectory 沙盒的Documents路径名称
//③Library路径
NSArray *libraryArr =NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryStr = [libraryArr objectAtIndex:0];
//NSLibraryDirectory 沙盒的Library路径
NSArray *cachesArr = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES);
NSString *cachesStr = [cachesArr objectAtIndex:0];
//NSCachesDirectory 沙盒的Library/Caches路径
//④tmp路径
NSString *tmpPath = NSTemporaryDirectory();
//⑤在沙盒中创建文件夹(在Documents下创建文件)
//Library/Preferences路径可通过这个方法获取
//获取Documents路径
NSArray *dmtsArr =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *dmtsStr = [dmtsArr objectAtIndex:0];
//创建新的路径
NSString *path = [dmtsStrstringByAppendingPathComponent:@"test/a.txt"];
4. 常见结构体
1) CGPoint/NSPoint
平面中的点,有x和y两个属性
CGPoint c1; c1.x = 3;c1.y = 4;
CGPoint c2 = {2,2};
CGPoint c3 = {.x = 5};
CGPoint c4 = CGPointMake(5,6);
NSPoint c4 = NSMakePoint(5,6);
2) CGSize/NSSize
表示平面的大小,有宽度width和高度height两个属性
CGSize s1;s1.width = 50;s1.height = 45;
CGSize s2 = CGSizeMake(50,50);
NSSize s3 = NSMakeSize(100,100);
3) CGRect/NSRect
平面中的矩形区域,有CGPoint类型的 origin(矩形左上角的点坐标)和CGSize类型的size(矩形大小)两个属性
CGRect r1;
r1.origin.x=4;r1.origin.y=5;
r1.size.width = 50;r1.size.height = 30;
CGRect r2 = {{4,5},{100,80}};
CGRect r3 = CGRectMake(10,10,200,100);
NSRect r4 = NSMakeRect(12,13,80,50);
5. NSNumber
1) NSNumber是处理数值类型的一个类,可以将基本数据类型包装成对爱你过,这样就可以间接将基本数据类型存进NSArray和NSDictionary中
2) 把基本数据类型转化为NSNumber类型
int a=5;
NSNumber *objA = [NSNumber numberWithInt:a];
类似的numberWithFloat,numberWithDouble等方法,把对应基本类型幻化为NSNumber类型
添加到数组中
NSMutableArray *arr = [NSMutableArrayarrayWithObjects:objA];
3) 把NSNumber类型转化为基本数据类型
NSNumber *n = arr[0];
int a = [n intValue];
4) 简写形式
[arr addObject:@(a)];//@(变量名) 表示把该变量(a)转化为NSNumber类型
[arr addObject:@10];//@数值 表示把数值包装成对象。
6. NSValue
NSNumber是NSValue的子类,NSValue主要用来把指针,CGRect结构体等包装成OC对象,以便存储。
//NSNumber是NSValue的子类,而NSNumber只能存放数值类型的数据,NSValue除了可以存放基本类型外,还可以存放结构体类型,如CGPoint/NSPoint,CGSize/NSSize,CGRange/NSRange,普通结构体等,然后可以添加到数组或字典中,以CGPoint为例。
//定义变量
CGPoint point = {10,20};
NSValue *pv = [NSValue valueWithPoint:point];
NSMutableArray *arr = [NSMutableArray array];
//把点添加到数组中
//[arr addObject:point];//数组不能存放结构体,只能存放OC对象
[arr addObject:pv];
NSLog(@"pv = %@",[arr firstObject]);
//取出数组的结构体元素,转化为结构体
//定义结构体变量
Time time = {12,12,12};
//把结构体转化为NSValue类型
//@encode(Time) 把Time生成一个常量字符串描述
NSValue *va = [NSValue valueWithBytes:&time objCType:@encode(Time)];
//把va添加到数组中
NSMutableArray *arr2 = [NSMutableArray arrayWithObject:va];
//定义一个新的结构体变量
Time t;
//把NSValue类型转化为普通结构体
[va getValue:&t];
NSLog(@"%d:%d:%d",t.hour,t.min,t.sec);
7. NSDate
1) NSDate用来表示时间,可以进行一些常见的日期\时间处理。一个NSDate对象就是一个时间,[NSDate data];返回的就是当前格林尼治标准时间
2) 格式化显示时间
//获取当前时间
//得到的是0时区时间,其他时区加减时间差就行。
NSDate *date = [NSDate date];
NSLog(@"%@",date);
//格式化时间
//创建时间格式化对象
NSDateFormatter *dtfmt = [NSDateFormatter new];
//日期显示格式
//yyyy 四位的年份
//MM 两位的月份
//dd 两位的天数
//HH 24小时制小时 hh 12小时制小时
//mm 两位的分
//ss 两位的秒
//设置格式
dtfmt.dateFormat = @"yyyy年MM月dd日 HH:mm:ss";
//把日期格式化,得到的是本地时间,并返回字符串类型
NSString *str = [dtfmt stringFromDate:date];
NSLog(@"time = %@",str);
3) 计算某个时间
//计算多少秒后的时间,NSTimeInterval就是double别名,这里表示时间间隔
NSTimeInterval t = 60*60*24;
//定义日期对象
NSDate *d = [NSDate dateWithTimeIntervalSinceNow:t];
NSDate *d2 = [NSDate dateWithTimeIntervalSinceNow:-t];
NSLog(@"d = %@",d);
NSLog(@"d2 = %@",d2);
4) 获得时间的各个部分
//获取日期的每个单元,年,月,日,时,分,秒
NSDate *cd = [NSDate date];
//NSCalendar为一个日历对象
NSCalendar *ca = [NSCalendar currentCalendar];
//NSDateComponents 日期组件类,有日期各单元的属性
NSDateComponents *cmp = [ca components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecondfromDate:cd];
//方法参数1:获得的对应单元,多个用|分隔; 参数2:日期
NSLog(@"%ld.%ld.%ld",cmp.year,cmp.month,cmp.day);
NSLog(@"%ld:%ld:%ld",cmp.hour,cmp.minute,cmp.second);
8. 集合对象的内存管理
1) 官方内存管理原则
I. 当调用alloc、new、copy(mutableCopy)方法产生一个新对象的时候,就必须在最后调用一次release或者autorelease
II. 当调用retain方法让对象的计数器+1,就必须在最后调用一次release或者autorelease
2) 集合的内存管理细节
I. 当把一个对象添加到集合中去时,这个对象会做了一次retain操作,计数器会+1
II. 当一个集合被销毁时,会对集合里面的所有对象做一次release操作,计数器会-1
III. 当一个对象从集合中移除时,这个对象会做一次release操作,计数器会-1
3) 普遍规律
I. 如果方法名是以add\insert开头,那么被添加的对象,计数器会+1
II. 如果方法名是以remove\delete开头,那么被移除的对象,计数器会-1.
9. Copy
1) 什么是copy
Copy的字面意思是“复制”、“拷贝”,是一个产生副本的过程。
对象拷贝的目的:要使用某个对象的数据,但是在修改对象的时候不影响原来的对象内容。
2) 特点
修改源文件的内容,不会影响副本文件
修改副本文件的内容,不会影响源文件
OC中的copy,指的就是对象的 拷贝。
作用:利用一个源对象产生一个副本对象。
修改源对象的属性和行为,不会影响副本对象
修改副本对象的属性和行为,不会影响源对象
3) copy的使用
一个对象可以调用copy或mutableCopy方法来创建一个副本对象。
copy:创建的是不可变副本
mutableCopy:创建的是可变副本。
4) 使用copy功能的前提
使用copy方法,需要遵守NSCopying协议,实现copyWithZone:方法。使用mutableCopy:需要遵守NSMutableCopying协议,实现mutableCopyZone:方法。
5) Copy的内存管理
① 当使用copy方法进行拷贝来创建对象时,是浅拷贝,即两个对象指向的是同一个内存空间,拷贝的是地址。
新旧对象时同一个对象,引用计数变为2.
② 当使用mutableCopy创建对象时,是深拷贝,即两个对象指向的是两个不同的内存空间,拷贝的是内容。
两个对象的引用计数都为1
③ 深复制(深拷贝,内容拷贝,deep copy)
源对象和副本对象是不同的两个对象
源对象的引用计数器不变,副本对象的计数器为1
本质:产生了新的对象
④ 浅复制(浅拷贝,指针拷贝,shallow copy)
源对象和副本对象是同一个对象
源对象(副本对象)的引用计数器+1,相当于做一次retain操作
本质:没有产生新的对象
10. @property中的copy关键字
1) 非ARC
① copy:只用于NSString\block
② retain:除NSString\block以外的OC对象
③ assign:基本的数据类型、枚举、结构体(非OC对象),当两个对象相互引用,一端用retain,一端用assign
2) ARC
① copy:只用于NSString\block
② strong:除NSString\block以外的OC对象
③ weak:当2个对象相互引用,一端用strong,一端用weak
④ assign:基本数据类型、枚举、结构体(非OC对象)
11. 自定义类实现copy操作
//定义一个类,并实现NSCopying协议
@interface Dog:NSObject<NSCopying>
@property (nonatomic,assogn)int speed;
@end
//实现方法
@implementation Dog
//返回一个副本对象
-(id)copyWithZone:(NSZone *)zone{
Dog*d = [[Dog alloc]init];
d.speed= self.speed;
returnd;
}
@end
#import <Foindation/Foundation.h>
int main(int argc,const char *argv[]){
@autoreleasepool{
Dog*jd = [Dog new];
jd.speed= 100;
//调用copy方法,系统会去调用copyWithZone:方法
Dog*d = [jd copy]; //d.speed = 100;
}
return 0;
}
12. 单例模式的实现
1) 单例模式概念
① 单例模式的意图是使类的对象称为系统中唯一的实例,提供一个访问点,供客户类共享资源。
② 使用情况:
a. 类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法
b. 这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码
③ 单例设计模式的要点
A. 某个类只能有一个实例
B. 它必须自行创建这个对象
C. 必须自行向整个系统提供这个实例
D. 为了保证实例的唯一性,必须将以下方法的实现进行覆盖
-(id)copyWithZone:(NSZone *)zone
+(id)allocWithZone:(NSZone *)zone
-(id)retain
-(NSUInteger)retainCount
-(oneway void)release
-(id)autorelease
E. 这个方法必须是一个静态类
2) 简单的单例模式设计
//单例类
#import <Foundation/Foundation.h>
@interface Singleton :NSObject<NSCopying>
@property (nonatomic,copy)NSString *name;
//单例的类,提供一个接入点
+(instancetype)shareInstances;
@end
#import "Singleton.h"
//定义全局变量
static Singleton *instances = nil;
@implementation Singleton
-(id)copyWithZone:(NSZone *)zone{
return self;
}
+(id)allocWithZone:(NSZone *)zone{
//线程保护
@synchronized(self) {
if (instances == nil) {
//调用父类的alloc
instances = [super allocWithZone:zone];
return instances;
}
}
return instances;
}
-(id)retain{
return self;
}
-(NSUInteger)retainCount{
return NSUIntegerMax;
}
-(oneway void)release{
}
-(id)autorelease{
return self;
}
//单例的接入点方法
+(instancetype)shareInstances{
//保证对象必须唯一
if (instances == nil) {
instances = [[Singleton alloc]init];
return instances;
}
return instances;
}
@end
//Person类
#import <Foundation/Foundation.h>
@interface Person : NSObject
-(void)run;
@end
#import "Person.h"
#import "Singleton.h"
@implementation Person
-(void)run{
//创建单例对象
Singleton *st = [Singleton shareInstances];
//调用set方法设置单例对象的属性值
st.name = @"hao a you";
}
@end
//Student类
#import <Foundation/Foundation.h>
@interface Student : NSObject
-(void)run;
@end
#import "Student.h"
#import "Singleton.h"
@implementation Student
-(void)run{
//创建单例对象
Singleton *st = [Singleton shareInstances];
NSLog(@"name = %@",st.name);
}
@end
//main函数
#import <Foundation/Foundation.h>
#import "Singleton.h"
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [Person new];
[p run];
Student *stu = [Student new];
[stu run];
}
return 0;
}
在Person类中对单例对象的属性进行设置,在Student类中进行访问时不会是空,而是在Person类中设置好的值。