讀取info.plist檔案:
NSDictionary *infoDict = [NSBundle mainBundle].infoDictionary;
NSString *version = infoDict[@"CFBundleVersion"];
一,屬性列表
屬性列表即plist檔案,實質是xml檔案。
注意點:
- 根節點只能是NSArray或者NSDictionary
- 如果物件是NSString、NSDictionary、NSArray、NSData、NSNumber等型別,就可以使用writeToFile:atomically:方法直接將物件寫到屬性列表檔案中
-
將一個NSDictionary物件歸檔到一個plist屬性列表中
// 將資料封裝成字典
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"母雞" forKey:@"name"];
[dict setObject:@"15013141314" forKey:@"phone"];
[dict setObject:@"27" forKey:@"age"];
// 將字典持久化到Documents/stu.plist檔案中
[dict writeToFile:path atomically:YES];
二,偏好設定
用於儲存APP的設定,例如是否記住密碼、是否接受推送、儲存字型大小等。
// 儲存資料
-(void)saveData
{
// 1.獲取偏好設定
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
// 2.儲存資料
[userDefaults setObject:@"傳智播客" forKey:@"itcastKey"];
[userDefaults setBool:YES forKey:@"isGoodKey"];
/*注意:UserDefaults設定資料時,不是立即寫入,而是根據時間戳定時地把快取中的資料寫入本地磁碟。所以呼叫了set方法之後資料有可能還沒有寫入磁碟應用程式就終止了。出現以上問題,可以通過呼叫synchornize方法強制寫入
*/
// 3.同步資料(iOS8)
[userDefaults synchronize];
}
// 讀取資料
-(void)readData
{
// 1.獲取偏好設定
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
// 2.讀取資料
NSLog(@"%@",[userDefaults objectForKey:@"itcastKey"]);
}
三,歸檔可以將任意型別的物件,編碼後以二進位制的形式儲存。
在使用plist進行資料儲存和讀取,只適用於系統自帶的一些常用型別才能用,且必須先獲取路徑相對麻煩;
偏好設定(將所有的東西都儲存在同一個資料夾下面,且主要用於儲存應用的設定資訊)
歸檔優勢:因為前兩者都有一個致命的缺陷,只能儲存常用的型別。歸檔可以實現把自定義的物件存放在檔案中。
注意點:
- 需要歸檔的自定義類,必須實現
<NSCoding>
協議,告訴系統需要歸檔和解檔哪些屬性。 - 若物件的屬性中有自定義型別,則該類也需要實現
<NSCoding>
協議。
// 儲存資料
-(void)saveData
{
// 1.建立物件
CZPerson *person = [CZPerson new];
person.name = @"Jack";
person.age = 18;
// 2.實現<NSCoding>協議
// 3.獲取檔案路徑
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documents stringByAppendingPathComponent:@"person.data"];
// 4.編碼並儲存(歸檔)
[NSKeyedArchiver archiveRootObject:person toFile:filePath];
}
// 讀取資料
-(void)readData
{
// 1.獲取檔案路徑
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documents stringByAppendingPathComponent:@"person.data"];
// 2.解檔
CZPerson *person = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@",person.name);
}
實現
<NSCoding>
協議 • encodeWithCoder什麼時候呼叫:物件歸檔時候呼叫
• encodeWithCoder作用:告訴系統物件裡的哪些屬性需要歸檔,怎麼去歸檔,根據一個key去歸檔,目的就是以後取的時候,也根據這個key去取資料。
// 編碼
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeInteger:_age forKey:@"age"];
}
• initWithCoder作用:告訴系統物件裡的哪些屬性需要解檔,怎麼去解檔,根據之前儲存的key去解檔
• initWithCoder是一個初始化方法,需要先初始化父類的,但是不能呼叫[super initWithCoder:],因為父類NSObject沒有遵守NSCoding協議。
3> initWithCoder什麼時候需要呼叫[super initWithCoder:]
• initWithCoder原理:只要解析檔案就會呼叫,xib,storyboard都是檔案,因此只要解析這兩個檔案,就會呼叫initWithCoder。
• initWithCoder是一個初始化方法,需要先初始化父類的,但是不能呼叫[super initWithCoder:],因為父類NSObject沒有遵守NSCoding協議。
3> initWithCoder什麼時候需要呼叫[super initWithCoder:]
• initWithCoder原理:只要解析檔案就會呼叫,xib,storyboard都是檔案,因此只要解析這兩個檔案,就會呼叫initWithCoder。
• 因此如果在storyboard使用自定義view,重寫initWithCoder方法,一定要呼叫[super initWithCoder:],因為只有系統才知道怎麼解析storyboard,如果沒有呼叫,就解析不了這個檔案。
// 解碼,例項化
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init])
{//將物件的一些屬性儲存,沒有設定的屬性不作儲存
_name = [aDecoder decodeObjectForKey:@"name"];
_age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
兩個方法的區別與使用場景
/// 解歸檔 : 這個方法是把檢視從bundle載入到記憶體.檢視的frame可能不準
//- (instancetype)initWithCoder:(NSCoder *)aDecoder
//{
// if (self = [super initWithCoder:aDecoder]) {
// NSLog(@"%s",__func__);
// }
// return self;
//}
/// 檢視被喚醒的方法.在這個方法裡面可以拿到準確frame的檢視
- (void)awakeFromNib
//- (instancetype)initWithCoder:(NSCoder *)aDecoder
//{
// if (self = [super initWithCoder:aDecoder]) {
// NSLog(@"%s",__func__);
// }
// return self;
//}
/// 檢視被喚醒的方法.在這個方法裡面可以拿到準確frame的檢視
- (void)awakeFromNib
{
}
//讀取JSON檔案,轉模型
+ (NSArray *)projects {
// 1. 檔案路徑
NSString *path = [[NSBundle mainBundle] pathForResource:@"more_project.json" ofType:nil];
// 2. 讀取檔案內容 - 二進位制資料
NSData *data = [NSData dataWithContentsOfFile:path];
// 3. 解析JSON 專門用來解析JSON的類 NSJSONSerialization
// 1. 檔案路徑
NSString *path = [[NSBundle mainBundle] pathForResource:@"more_project.json" ofType:nil];
// 2. 讀取檔案內容 - 二進位制資料
NSData *data = [NSData dataWithContentsOfFile:path];
// 3. 解析JSON 專門用來解析JSON的類 NSJSONSerialization
/**
看到options先傳0.沒有達到效果再來看列舉值
*/
NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
// 宣告一個可變的陣列
NSMutableArray *projects = [NSMutableArray array];
// 4. 遍歷資料,把字典轉成模型 - 使用block來遍歷陣列
[json enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CZProject *project = [CZProject projectWithDict:obj];
[projects addObject:project];
*/
NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
// 宣告一個可變的陣列
NSMutableArray *projects = [NSMutableArray array];
// 4. 遍歷資料,把字典轉成模型 - 使用block來遍歷陣列
[json enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CZProject *project = [CZProject projectWithDict:obj];
[projects addObject:project];
}];
// 將可變陣列,變成不可變 : 將執行緒不安全的類,變成了執行緒安全的類.同時,不可變的陣列,外界不能修改的.
return projects.copy;
}