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