NSFileManger的介绍和用法(文件操作)
1、NSFileManager的介绍
NSFileManager:用来管理文件系统的,进行常见的文件或文件夹操作(拷贝、剪切、创建等)
NSFileManager使用了单例模式singleton,使用defaultManager方法可以获得那个单例对象
2、NSFileManager的基本使用(常见的判断)
NSString
*filePath = @"/Users/ZacharyUE/Desktop/str.plist”;//先给一个路径
NSString
*filePath2 = @"/Users/ZacharyUE/Desktop";
//NSFileManager
用于判断
//创建文件管理对象,单例对象(在程序运行期间,只有一个对象存在)
NSFileManager
*fm = [NSFileManager
defaultManager];
//1)判断文件是否存在
BOOL
isYES = [fm fileExistsAtPath:filePath];
NSLog(@"%d", isYES);
//2)判断是否是一个目录
if
(isYES) {
BOOL
isDir;
[fm fileExistsAtPath:filePath2
isDirectory:&isDir];
if
(isDir) {
NSLog(@"这是一个目录");
} else
{
NSLog(@"不是一个目录");
}
}
//3)判断文件是否可读
isYES = [fm isReadableFileAtPath:filePath];
NSLog(@"%d", isYES);
//4)是否可写
isYES = [fm isWritableFileAtPath:filePath2];
NSLog(@"%d", isYES);
//5)是否可删除
isYES = [fm isDeletableFileAtPath:filePath];
NSLog(@"%d", isYES);
3、NSFileManager用法深入1
-NSFileManager的文件访问
//创建文件对象
NSFileManager
*fm = [NSFileManager
defaultManager];
NSString
*filePath =
@"/Users/ZacharyUE/Desktop/str.plist”; //文件路径
NSString
*dirPath = @"/Users/ZacharyUE/Desktop/儒释道”;
//目录路径
//1)何如获取文件的信息(属性)
NSDictionary
*dic = [fm
attributesOfItemAtPath:filePath
error:nil];
NSLog(@"%@", dic);
NSLog(@"%@, %@", [dic
objectForKey:@"NSFileOwnerAccountName"], dic[@"NSFileOwnerAccountName"]);//字典通过key获取值,两种方式
//2)获取指定目录下文件及子目录
//使用递归的方式
获取当前目录及子目录下的所有文件及文件夹
NSArray
*arr = [fm subpathsAtPath:dirPath];
//这种方法不是使用递归的方式实现
arr = [fm subpathsOfDirectoryAtPath:dirPath
error:nil];
NSLog(@"%@", arr);
//3)获取指定目录下的子目录(不在获取后代路径,即不在获取子目录下的信息)
arr = [fm contentsOfDirectoryAtPath:dirPath
error:nil];
NSLog(@"%@", arr);
4、NSFileManager用法深入2
//第一步,必须有文件管理对象
NSFileManager
*fm = [NSFileManager
defaultManager];
//如何创建目录(路径:/Users/ZacharyUE/Desktop/dir)
NSString
*createDirPath = @"/Users/ZacharyUE/Desktop/dir";
/*
createDirectoryAtPath:@"路径" withIntermediateDirectories:YES/NO
YES/NO:会把缺失文件夹补上来,后者如果上级文件夹确实,会报错
attributes:属性的字典
error:错误对象
*/
BOOL
isYES = [fm createDirectoryAtPath:createDirPath
withIntermediateDirectories:NO
attributes:nil
error:nil];
if
(isYES) {
NSLog(@"%d", isYES);
}
//如何创建文件
NSString
*str = @"我shi最棒的!";//写入到@"/Users/ZacharyUE/Desktop/dir/me.txt";
//以下的createDirPath =
@"/Users/ZacharyUE/Desktop/dir/me.txt";
//1)writeToFile
//2)createFileAtPath
/*
createFileAtPath:@"路径" contents:NSData类型的数据
attributes:文件的属性的字典
创建NSData:是一个处理二进制数据的类
将NSString--------》NSData
*/
NSData
*data = [str dataUsingEncoding:NSUTF8StringEncoding];
BOOL
isYES = [fm createFileAtPath:createDirPath
contents:data
attributes:nil];
NSLog(@"%d", isYES);
//如何copy文件
NSString
*copyPath = @"/Users/ZacharyUE/Desktop/dir/xxx/me.txt";
BOOL
isYES = [fm copyItemAtPath:createDirPath
toPath:copyPath
error:nil];
NSLog(@"%d", isYES);
//如何移动文件
NSString
*movePath = @"/Users/ZacharyUE/Desktop/dir/aaa/me.txt";
[fm
moveItemAtPath:createDirPath
toPath:movePath
error:nil];
//如何删除文件,@"/Users/ZacharyUE/Desktop/dir/me.txt"
[fm
removeItemAtPath:createDirPath
error:nil];
5、NSFileManager文件下载的思路
1)发送请求给服务器,要求下载某个文件
2)服务器发出响应,返回文件数据
3)手机客户端利用NSData来存放服务器返回的文件数据
4)利用NSFileManager将NSData里面的文件数据写到新的文件中
6、iOS沙盒(sandbox)机制
每个iOS应用都有自己的应用沙盒,应用沙盒就是文件系统目录,与其他应用的文件系统隔离,iOS系统不允许访问其他应用的应用沙盒。
在iOS8中已经开放访问(extension),对几个固定系统区域的扩展机制。
应用沙盒一般包含几个文件目录:应用程序包、Documents、Libaray(子目录Caches和Preferences)、tmp
应用程序包:包含所有的资源文件和可执行文件。
Documents:保存应用运行时生成的需要持久化的数据,iTunes会自动备份该目录。
tmp:保存应用运行时所需的零时数据,使用完后相应地文件从该目录删除。未运行时,系统也可能清除该目录的文件,iTunes不会同步该目录。iPhone重启时,该目录下的文件会丢失。
Libaray:存储程序的默认设置和其它状态信息,iTunes会自动备份该目录。
Libaray/Caches:存储缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出时删除。
Libaray/Preference:保存应用的所有偏好设置(配置信息\SQLite),iOS的Settings(设置)应用会在该目录中查找应用的设置信息,iTunes会自动备份该目录。
//沙盒路径获取方法:
//1)沙盒的路径
NSString
*sandBoxPath = NSHomeDirectory();
NSLog(@"sandBoxPath = %@", sandBoxPath);//在Mac下,用户根目录
//2)tmp路径
NSString
*tmpPath = NSTemporaryDirectory();
NSLog(@"tmpPath = %@", tmpPath);
//2)Documents路径
// NSSearchPathForDirectoriesInDomains(要查找的目录,
是否使用主目录, YES/NO是否获取全路径)
NSArray
*arr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSLog(@"%@", arr);
//4)Library、caches同理
arr = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask,
YES);
NSLog(@"%@", arr);
//5)preferences路径,在Libaray的基础上,拼接/Preferences
NSString
*filePath = [arr lastObject];
//stringByAppendingPathComponent用于拼接,也可以创建文件:@“Preferences/a.txt"
NSString
*str = [filePath stringByAppendingPathComponent:@"Preferences"];
NSLog(@"%@", str);
7、常见的结构体
1)NSPoint和CGPoint的使用(点)
/* Points. */
//二维平面的一个点
struct
CGPoint {
CGFloat
x;
CGFloat
y;
};
typedef
struct
CGPoint CGPoint;//NSPoint是CGPoint的别名,没区别
CGPoint
c1;//c1是CGPoint结构体类型的变量
c1.x
= 10;
c1.y
= 10;
CGPoint
c2 = {10,
10};
//OC特有的赋值
CGPoint
c3 = CGPointMake(10,
10);
NSPoint
c4 = NSMakePoint(5,
5);
2)NSSize和CGSize的使用(大小)
/* Sizes. */
//表示平面的面积
struct
CGSize {
CGFloat
width;//宽
CGFloat
height;//高
};
typedef
struct
CGSize CGSize;
//同理,也有特有的赋值方式,形式与上面类似CGSizeMake和NSMakeSize
3)NSRect和CGRect的使用(矩形)
/* Rectangles. */
//表示从左上角某个点开始的矩形区域
struct
CGRect {
CGPoint
origin;//开始点
CGSize
size;//大小
};
typedef
struct
CGRect CGRect;
CGRect
r1;
r1.origin.x
=
0;
r1.origin.y
=
0;
r1.size.width
=
200;
r1.size.height
=
80;
CGRect
r2 = {{0,
0}, {10,
20}};
//OC特有赋值方式
CGRect
r3 = CGRectMake(0,
0,
30,
80);
NSRect
r4 = NSMakeRect(0,
0,
89,
90);
//快捷查看值的方法,转换为字符串
NSLog(@"r4 = %@",
NSStringFromRect(r4));
//同理,上面的Size和Point都可以
4)常见结构体的使用注意
苹果官方推荐使用CG开头
8、NSNumber的使用
1)NSNumber的介绍和使用
OC中处理数字的一个类
NSArray和NSDictionary中只能存放OC对象,需要先将基本类型包装成对象,这样就可以存放到数组或字典
2)NSNumber的创建
int
a =
10;
NSNumber
*intObj = [NSNumber
numberWithInt:a];//其他类型同理
NSArray
*array = [NSArray
arrayWithObjects:intObj,
nil];
NSLog(@"%@", array);
3)从NSNumber对象中获取到基本数据类型
float
b =2.3f;
NSNumber
*floatObj = [NSNumber
numberWithFloat:b];
[array addObject:floatObj];
NSLog(@"%@", array);
//数组的第一个元素和第二个元素相加
//1)取出数组的元素
//2)把数组元素转换为基本数据类型
NSNumber
*n1 = array[0];
int
a1 = [n1 intValue];//获取对象的整形值
NSNumber
*n2 = array[1];
float
b1 = [n2 floatValue];
a1 = a1 + b1;
NSLog(@"%d", a1);
简写形式:@(变量名)、@数值或@YES,都是把变量、数值或YES包装成对象
9、NSValue的介绍和使用
NSNumber是NSValue的子类,NSValue主要是把指针,CGRect结构体等包装成OC对象,以便存储。
(int/float/char/pointers/structures/object ids)
NSValue类的目标:允许以上数据类型的数据结构能够被添加到集合里,如NSArray和NSDictionary
为了方便结构体和NSValue的转换,Foundation提供了一下方法:
1)存储结构体到集合
+ (NSValue
*)valueWithPoint:(NSPoint)point;
+ (NSValue
*)valueWithSize:(NSSize)size;
+ (NSValue
*)valueWithRect:(NSRect)rect;
//创建一个结构体变量,保存一个点
CGPoint
p1 = CGPointMake(10,
10);
//将结构体包装为NSValue对象
NSValue
*pointObj = [NSValue
valueWithPoint:p1];
NSMutableArray
*array = [NSMutableArray
arrayWithObjects:pointObj,
nil];
NSLog(@"%@", array);
//创建一个结构体,保存Size
CGSize
s1 = CGSizeMake(20,
20);
NSValue
*sizeObj = [NSValue
valueWithSize:s1];
[array addObject:sizeObj];
NSLog(@"%@", array);
//创建一个结构体,保存Rect
CGRect
r1 = CGRectMake(1,
1,
22,
33);
[array addObject:[NSValue
valueWithRect:r1]];
NSLog(@"%@", array);
2)从NSValue对象取出之前包装的结构体
- (NSPoint)pointValue;
- (NSSize)sizeValue;
- (NSRect)rectValue;
//取最后的值
NSValue
*lastValue = [array lastObject];
NSRect
r2 = [lastValue rectValue];
NSLog(@"%@",
NSStringFromRect(r2));
//转换为字符串
//自定义结构体
typedef
struct data {
int
year;
int
month;
int
day;
} MYData;
//定义结构体变量
MYData
md = {2015,
9,
3};
//将自定义结构体包装成NSValue对象
//@encode(MYData)
作用,把MYData类型生成一个常量字符串描述
NSValue
*mdObj = [NSValue
valueWithBytes:&md
objCType:@encode(MYData)];
//保存自定义结构体,到数组
NSMutableArray
*arr = [NSMutableArray
arrayWithObjects:mdObj,
nil];
//从数组取出NSValue对象
MYData
md1;
[[arr
objectAtIndex:0]
getValue:&md1];//getValue获取的值,保存到md1中
//从对象中,取出结构体变量的值
NSLog(@"%d-%d-%d", md1.year,
md1.month, md1.day);
10、NSDate的介绍和使用
1)NSDate的介绍和使用
NSDate可以表示时间,可以进行一些常见的日期、时间处理。一个NSDate对象就代表一个时间,[NSDate
date]返回的就是当前时间。
//NSDate
是OC中提供日期时间处理的一个类
//1)获取当前时间
NSDate
*d1 = [NSDate
date];//创建一个日期时间对象对象
//北京东八区,打印的时间(格林威治时间)+8
= 现在时间
NSLog(@"%@", d1);
//2)格式化显示时间
NSDateFormatter
*formatter = [NSDateFormatter
new];
//设置日期的显示格式
//yyyy:年份 MM:月份
dd:天数
//HH:24小时制 hh:12小时制
//mm:分钟数 ss:秒数
formatter.dateFormat
=
@"yyyy年MM月dd日
HH:mm:ss";
NSString
*dateStr = [formatter stringFromDate:d1];
NSLog(@"%@", dateStr);
//3)计算时间
//1、计算明天的此刻时间(24小时之后的时间)
NSTimeInterval
t =
60 *
60 *
24;
NSDate
*tom = [NSDate
dateWithTimeIntervalSinceNow:t];
NSDateFormatter
*formatter = [NSDateFormatter
new];//格式化显示
formatter.dateFormat
=
@"yyyy-MM-dd hh:mm:ss";
NSString
*str = [formatter stringFromDate:tom];
NSLog(@"%@", str);
//2、计算昨天的此刻时间(-t:24小时之前的时间)
NSDate
*yest = [NSDate
dateWithTimeIntervalSinceNow:-t];
str = [formatter stringFromDate:yest];
NSLog(@"%@", str);
//也可以用当前时间,进行加减时间
NSDate
*now = [NSDate
date];
NSDate
*yest2 = [now addTimeInterval:-t];//该方法已经被放逐了
str = [formatter stringFromDate:yest2];
NSLog(@"%@", str);
//4)日期时间对象的使用
//1、NSCalendar
日期类,可以帮助快速获取年月日
时分秒的信息
NSDate
*d = [NSDate
date];
//创建日期对象
NSCalendar
*cal = [NSCalendar
currentCalendar];
//参数:获取日期的哪个单元(可以多个单元,|)
当前日期对象
NSDateComponents
*com = [cal
components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay
fromDate:d];
NSLog(@"%ld-%ld-%ld", com.year,
com.month, com.day);
//2、时间差方法:components:<#(NSCalendarUnit)#> fromDate:<#(nonnull NSDate *)#> toDate:<#(nonnull
NSDate *)#> options:<#(NSCalendarOptions)#>
11、集合对象的内存管理
1)集合内存管理
//创建对象
Person
*p = [Person
new];
//1
//定义数组,并且把P放到数组中
//规律:只要把对象放入数组,retainCount+1
//NSArray *arr = [NSArray arrayWithObject:p];//2
NSMutableArray
*arr = [NSMutableArray
array];
[arr
addObject:p];//2
//上面都是快速创建对象,会被加入自动释放池。如果是[[NSArray alloc] init]、copy或new,则不会加入自动释放池,则该对象不会被释放,不会调用dealloc
NSLog(@"p.retainCount = %lu", p.retainCount);
[p release];
//规律2:数组被销毁时,对对象发送了一次release消息
//销毁顺序:数组先挂-----》数组向其中的对象也发送release
NSLog(@"p.retainCount = %lu", p.retainCount);
//结论:
//1)当对象被添加到数组中,对象的引用计数+1
//2)数组被销毁时,对对象发送了一次release消息
//3)数组被销毁了,其中的对象不一定被销毁
2)集合内存管理总结
1、当调用alloc、new、copy(mutablecopy)方法产生一个新对象的时候,就必须在最后调用一次release或者autorelease。因为不会加入自动释放池。
2、retain和release必须成对出现
3、当一个对象添加集合,retain+1,retainCount+1
当一个集合(快速创建)被销毁,集合所有对象均被release一次,retainCount-1
当一个对象从集合中移除,这个对象会被release一次,retainCount-1
4、普遍规律:当方法名是add\insert开头 计数器+1
当方法名是remove\delete开头,计数器-1
12、copy概念及入门
1、copy概念
copy:复制,拷贝,是产生一个副本的过程。
对象拷贝的目的:要使用某个对象的数据,但是在修改对象的时候不影响原来的对象内容。源文件和副本文件,互不影响。
copy功能:一个对象可以调用copy或mutableCopy方法创建一个副本对象
copy:创建不可变副本(如NSString)
mutableCopy:创建可变副本(如NSMutableString)
copy功能的前提:1)浅拷贝copy:需要遵守NSCopy协议,实现copyWithZone:方法
@protocol
NSCopying
- (id)copyWithZone:(nullable
NSZone *)zone;
@end
2)深拷贝mutableCopy:需要遵守NSMutableCopying协议,实现mutableCopyWithZone:方法
@protocol
NSMutableCopying
- (id)mutableCopyWithZone:(nullable
NSZone
*)zone;
@end
2、copy快速入门
不可变对象,copy 产生不可变对象
不可变对象,mutableCopy 产生可变对象
可变对象,copy 产生不可变对象
可变对象,mutableCopy 产生可变对象
13、copy与内存管理
浅拷贝:只是拷贝了地址,并没有真正的分配新的内存空间(源对象引用计数+1,副本对象指向源对象,两者一样)
深拷贝:分配了新的内存空间(源对象引用计数不变,副本对象为1)
14、@property中的copy关键字
1)MRC:
1、copy:只用于NSString和block
2、retain:除NSString和block以外的对象
3、assign:基本数据类型、枚举、结构体(非OC对象)。当两个对象互相引用时,一段assign,一段retain
2)ARC:
1、copy:只用于NSString和block
2、strong:除NSString和block以外的对象
3、weak:当两个对象互相引用时,一段weak,一段strong
4、assign:基本数据类型、枚举、结构体(非OC对象)
@property
(nonatomic,
copy)
NSString
*name;
#import
<Foundation/Foundation.h>
#import
"Person.h"
int
main(int
argc, const
char * argv[]) {
@autoreleasepool
{
Person
*p = [[Person
alloc]
init];
NSMutableString
*str = [NSMutableString
string];
[str appendString:@"xxx"];
p.name
= str;
NSLog(@"%@", p.name);
//使用copy时,防止这种无理的赋值。name得到的只是str的副本,再改变str不会影响name
[str appendString:@"ooo"];
NSLog(@"%@", p.name);
[p release];
}
return
0;
}
15、为自定义的类实现copy操作
步骤:1、新建Person类
2、为Person类实现copy操作
1)让Person类遵守NSCopying协议
2)实现copyWithZone方法,该方法返回一个对象的副本
3)在copyWithZone方法中,创建一个新的对象,并设置该对象的数据与现有对象一致,且返回该对象
3、创建Person对象,调用copy方法,查看地址
参数zone:表示空间,指定了zone,就可以指定新建对象对应的内存空间。如今开发中,zone几乎可以忽略
例子:1、
@interface
Dog : NSObject<NSCopying>
@property
(nonatomic,
assign)
int
tuiNum;
@property
(nonatomic,assign)
int
speed;
@end
2、
@implementation
Dog
- (id)copyWithZone:(nullable
NSZone *)zone {
NSLog(@"copy完毕");
//互不影响,需申请新空间
Dog
*d = [[Dog
alloc]
init];
d.speed
=
self.speed;
d.tuiNum
=
self.tuiNum;
//返回新空间的地址
return
d;
}
@end
3、
Dog
*dog = [Dog
new];
dog.speed
= 230;
dog.tuiNum
= 8;
//虽然重写copyWithZone方法,依然调用copy。历史原因
Dog
*yellowDog = [dog copy];
NSLog(@"%d,%d", yellowDog.speed,
yellowDog.tuiNum);
16、简单的单例模式实现
1)理解单例模式概念
单例模式(singleton):类的对象成为系统中唯一的实例,提供一个访问点,供客户类共享资源
单例使用场景:1、类只能够有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法
2、这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码
2)单例模式的实现
1、SingletonTools单例工具类
#import
<Foundation/Foundation.h>
@interface
SingletonTools : NSObject<NSCopying>
@property
(nonatomic,
assign)
int
num;
@property
(nonatomic,
copy)
NSString
*text;
//单例的类,提供一个接入点
+(instancetype)shareInstances;
//防止创建新的对象或者破坏该单例对象,需重写以下方法
-(id)copyWithZone:(NSZone
*)zone;
+(id)allocWithZone:(NSZone
*)zone;
-(id)retain;
-(NSUInteger)retainCount;
-(oneway
void)release;
-(id)autorelease;
@end
-------------------------------------------------------------------------------
#import
"SingletonTools.h"
//定义一个全局变量
static
SingletonTools *instances =
nil;//static增长使用周期,下次使用还有值
@implementation
SingletonTools
//单例接入点方法
+(instancetype)shareInstances {
//目的:保证对象必须唯一
if
(instances
== nil) {
//创建一个对象
instances
= [[SingletonTools
alloc]
init];
return
instances;
}
return
instances;
}
//防止创建新的对象或者破坏该单例对象,需重写以下方法
-(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 1;
}
-(oneway
void)release {
}
-(id)autorelease {
return
self;
}
@end
2、Person类
#import
<Foundation/Foundation.h>
@interface
Person : NSObject
-(void) run;
@end
----------------------------------------------------------------------------------------
#import
"Person.h"
#import "SingletonTools.h"
@implementation
Person
-(void) run {
//创建单例对象
SingletonTools
*st = [SingletonTools
shareInstances];
st.num
= 500;
st.text
= @"xxxxx";
}
@end
3、Dog类
#import
<Foundation/Foundation.h>
@interface
Dog : NSObject
-(void)run;
@end
--------------------------------------------------------------------------------------
#import
"Dog.h"
#import "SingletonTools.h"
@implementation
Dog
-(void)run {
SingletonTools
*st = [SingletonTools
shareInstances];
NSLog(@"%d,%@", st.num,
st.text);
}
@end
4、main
#import
<Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
int
main(int
argc, const
char * argv[]) {
@autoreleasepool
{
Person
*p = [Person
new];
[p run];
Dog
*d = [Dog
new];
[d run];//通过单例,d也可以访问p的数据
//而且在重写方法后,并不需要在意在Dog类的run中是如何创建单例对象(快速或者alloc)
//单例实现了两个不相干的类的数据传输
}
return
0;
}
Console:500,xxxxx