沙河主要子目錄:
/AppName.app:存放應(yīng)用程序自身
/Documents/:這是文檔目錄。有關(guān)應(yīng)用的所有數(shù)據(jù)文件應(yīng)該寫入到這個目錄下,這個目錄用于存儲用戶數(shù)據(jù)或者其他應(yīng)該定期備份的信息。
/Library/:默認(rèn)設(shè)置,下面有一些規(guī)范定義的的子目錄,當(dāng)然也可以自定義子目錄,用于存放應(yīng)用的文件,但是不宜存放用戶數(shù)據(jù)文件,和document一樣會被itunes同步,但不包括caches子目錄
/Library/Preferences,這里存放程序規(guī)范要求的首選項(xiàng)文件,通過NSUserDefaults來獲取和設(shè)置首選項(xiàng)。
/Library/Caches,保存應(yīng)用的持久化數(shù)據(jù),用于應(yīng)用升級或者應(yīng)用關(guān)閉后的數(shù)據(jù)保存,不會被itunes同步,所以為了減少同步的時間,可以考慮將一些比較大的文件而又不需要備份的文件放到這個目錄下
/tmp/,保存應(yīng)用數(shù)據(jù),但不需要持久化的,在應(yīng)用關(guān)閉后,該目錄下的數(shù)據(jù)將刪除,也可能系統(tǒng)在程序不運(yùn)行的時候做清除
//打開是模擬器的路徑
模擬器的app是systemData。
1、這是沙盒的入口文件(可直接打?。?/p>
NSString?*homeDirectory?=?NSHomeDirectory();??
NSLog(@"path:%@",?homeDirectory); ?
2、獲取document目錄
? ? //第一種拼接辦法
? ? NSString *documentPath = [NSHomeDirectory() stringByAppendingString:@"document"];
? ? //第二種函數(shù)辦法(因?yàn)榇撕瘮?shù)返回的是數(shù)組)
? ? NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObject];
3、獲取Cache目錄
//第一種拼接辦法
? ? NSString *NSCachesDirectory = [NSHomeDirectory() stringByAppendingString:@"Cache"];
? ? //第二種函數(shù)辦法(因?yàn)榇撕瘮?shù)返回的是數(shù)組)
? ? NSString *NSCachesDirectorys = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)firstObject];
4、獲取Library目錄
? ? //第一種拼接辦法
? ? NSString *libraryPath = [NSHomeDirectory() stringByAppendingString:@"library"];
? ? //第二種函數(shù)辦法(因?yàn)榇撕瘮?shù)返回的是數(shù)組)
? ? NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)firstObject];
5、獲取Tmp目錄(也可以直接訪問的存儲空間)
NSString?*tmpDir?=?NSTemporaryDirectory();??
?NSLog(@"%@",?tmpDir); ?
//平時經(jīng)常用document。
//其實(shí)info.plist和storyboard的文件都是可以解析成xml的,可以查看
一,解析info.plist文件(plist存儲)
NSString *plistPath = [[NSBundle mainBundle]pathForResource:@"Info" ofType:@"plist"];
? ? //拿到對應(yīng)的plist字典
? ? NSDictionary *plistDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
? ? //可以對字典做相應(yīng)的操作(讀數(shù)據(jù))
? ? NSArray *allKey = [plistDictionary allKeys];
? ? //也可以寫數(shù)據(jù)(寫到對應(yīng)的沙盒里)
? ? NSString *docStr =? [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES).firstObject stringByAppendingPathExtension:@"newFile"];
? ? [plistPath writeToFile:docStr atomically:YES];
//其實(shí)為沙盒存儲,其中為判斷文件是否已存在方法,
//盡量不用數(shù)字路經(jīng)中,
[NSFileManager defaultManager] fileExistsAtPath:fullPath]
二,NSUserdefault存儲
開發(fā)的兩個方法
存數(shù)據(jù)
[[NSUserDefaults standardUserDefaults] setObject:@"111" forKey:@"nameFiled"];
讀數(shù)據(jù)
[[NSUserDefaults standardUserDefaults] objectForKey:@"nameFiled"];
還有一種是當(dāng)新版本時,顯示某界面的操作,是拿到本次的版本號,存到偏好設(shè)置里面,當(dāng)下次啟動的時候,查看版本號是否和之前一致,判斷是否顯示
//需要在application里設(shè)置拿到plist的CFBundleShortVersionString查看當(dāng)前版本。在從NSUserDefaults里拿到本地版本,這樣來判斷是否為第一次打開該版本。
//需要在程序結(jié)束后把本地版本存起來。
NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults;
? ? NSString *currentVersion = [NSBundle mainBundle].infoDictionary[@"CFBundleShortVersionString"];
? ? NSString *localVersion = [userDefaults valueForKey:@"localVersion"];
!以上為沙盒存儲,但是只能存儲簡單的數(shù)據(jù),但是不能存儲自定義模型數(shù)據(jù)。
三,NSKeyedArchiver,NSKeyedUnarchiver歸檔
//歸檔是序列化的過程,反歸檔是反序列化的過程,
1,蘋果自帶數(shù)據(jù)歸檔和反歸檔
? ? self.data = [NSKeyedArchiver archivedDataWithRootObject:@[@"11",@"22"] requiringSecureCoding:YES error:nil];
? ? //反歸檔
? ? NSArray *dataArray = [NSKeyedUnarchiver unarchivedObjectOfClass:NSArray.class fromData:self.data error:nil];
2,自定義對象數(shù)據(jù)
//自定義對象的歸檔和反歸檔只要對象換一下就可以。但是對于自己寫的model需要操作寫數(shù)據(jù)。
要支持<NSSecureCoding>的協(xié)議
同時實(shí)現(xiàn)三個方法
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
? ? [aCoder encodeObject:self.nameField forKey:@"name"];
? ? [aCoder encodeInteger:self.age forKey:@"age"];
? ? }
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
? ? if(self = [super init])
? ? {
? ? ? ? self.nameField = [aDecoder decodeObjectForKey:@"name"];
? ? ? ? self.age = [aDecoder decodeIntegerForKey:@"age"];
? ? }
? ? return self;
}
+ (BOOL)supportsSecureCoding
{
? ? return YES;
}
http://www.itdecent.cn/p/3463b905d3dc 是歸檔詳解
四,SQLite存儲
//頭文件引入#import "sqlite3.h"
//內(nèi)嵌式(嵌入到一些小系統(tǒng)里面)占用資源也很低,支持window/linux/unix等等主流pc端操作,
支持的五種類型
1,NULL:表示該值為NULL值。
2,INTEGER:整型值。
3,REAL:浮點(diǎn)值。
4,TEXT:文本字符串,存儲使用的編碼方式為UTF-8,UTF-16等。
5,BLOB:二進(jìn)制大對象是人意類型的數(shù)據(jù)。
SQLite常見函數(shù)
splite3_open
sqlite3_close
sqlite3_exec
sqlite3_prepare_v2
sqlite3_step
sqlite3_column_text
想要在工程中使用,必須要先導(dǎo)入該工程
在general下有一個Linked Frameworks and Libraries,點(diǎn)擊+,引入libsqlite3.tbd。之后項(xiàng)目就會出現(xiàn)Frameworks的文件夾。
//以下為聲明的一些方法。(用于實(shí)現(xiàn)增刪改查)
- (void)createDB:(NSString *)dbName;
- (void)createTab:(NSString *)tabName;
- (void)insertMessage:(LHBMessage *)message;
- (void)deleteMessage:(NSString *)name;
- (void)updateMessage:(LHBMessage *)message;
- (NSArray<LHBMessage *>*)queryMessage;
- (NSArray<LHBMessage *>*)queryMessageByName:(NSString *)name;
- (void)dropTable:(NSString *)table;
//一下為各方法的實(shí)現(xiàn)
//數(shù)據(jù)庫打開之后就要隨時關(guān)閉,否則會浪費(fèi)資源
- (void)createDB:(NSString *)dbName
{
//? ? 1,查找沙盒
? ? NSString *str = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES).firstObject;
? ? NSLog(@"%@",str);
//? ? 2,拼接數(shù)據(jù)庫
? ? NSString *strDocument = [str stringByAppendingPathComponent:dbName];
//? ? 3,常用數(shù)據(jù)庫(UTF8String是oc轉(zhuǎn)c語言)
? ? int result = sqlite3_open([strDocument UTF8String],&_sqlite);
? ? if(result == SQLITE_OK){
? ? ? ? NSLog(@"數(shù)據(jù)庫創(chuàng)建成功");
? ? }else{
? ? ? ? NSLog(@"數(shù)據(jù)庫創(chuàng)建失敗");
? ? }
}
- (void)createTab:(NSString *)tabName
{
? ? //創(chuàng)建table。
? ? NSString *sql = [NSString stringWithFormat:@"create table %@(id integer primary key autoincrement, name text,phone text,address text)",tabName];
? ? NSLog(@"%@",sql);
? ? char *error;
? ? //c語言,數(shù)據(jù)庫執(zhí)行函數(shù),兩個null代表不需要回調(diào),最后一個參數(shù)代表錯誤。
? ? int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, &error);
? ? if(result == SQLITE_OK){
? ? ? ? NSLog(@"table創(chuàng)建成功");
? ? }
? ? else{
? ? ? ? NSLog(@"table創(chuàng)建失敗%s",error);
? ? }
? ? //sqlite3_close(_sqlite);
}
- (void)insertMessage:(LHBMessage *)message
{
? ? NSString *sql = [NSString stringWithFormat:@"insert into test(name,phone,address) values ('%@','%@','%@')",message.name,message.phone,message.address];
? ? int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, NULL);
? ? if(result == SQLITE_OK){
? ? ? ? NSLog(@"插入成功!");
? ? }
? ? else{
? ? ? ? NSLog(@"插入失??!");
? ? }
}
//一般很少進(jìn)行數(shù)據(jù)庫刪除操作,要使用一定要進(jìn)行一個彈窗提示,或者執(zhí)行刪除操作把該屬性設(shè)為值,這樣就可以達(dá)到查詢時找不到該數(shù)據(jù)的效果
- (void)deleteMessage:(NSString *)name
{
? ? NSString *sql = [NSString stringWithFormat:@"delete from test where name = '%@'",name];
? ? int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, NULL);
? ? if(result == SQLITE_OK){
? ? ? ? NSLog(@"刪除成功!");
? ? }
? ? else{
? ? ? ? NSLog(@"刪除失??!");
? ? }
}
- (void)updateMessage:(LHBMessage *)message
{
? ? NSString *sql = [NSString stringWithFormat:@"update test set phone = '%@' where name = '%@'",message.phone,message.name];
? ? int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, NULL);
? ? if(result == SQLITE_OK){
? ? ? ? NSLog(@"更新成功!");
? ? }
? ? else{
? ? ? ? NSLog(@"更新失?。?);
? ? }
}
- (NSArray<LHBMessage *> *)queryMessage
{
? ? NSString *sql = [NSString stringWithFormat:@"select * from test"];
? ? //sql語句的內(nèi)部結(jié)構(gòu)
? ? sqlite3_stmt *stmt;
? ? NSMutableArray *message = [[NSMutableArray alloc]init];
? ? int result = sqlite3_prepare_v2(_sqlite, [sql UTF8String], -1, &stmt, NULL);
? ? if(result == SQLITE_OK){
? ? ? ? while (sqlite3_step(stmt) == SQLITE_ROW) {
? ? ? ? const char *nameStr =(const char *)sqlite3_column_text(stmt, 1);
? ? ? ? const char *phoneStr =(const char *)sqlite3_column_text(stmt, 2);
? ? ? ? const char *addressStr =(const char *)sqlite3_column_text(stmt, 3);
? ? ? ? ? ? LHBMessage *lMessage = [[LHBMessage alloc]initWithObject:[NSString stringWithUTF8String:nameStr] withPhone:[NSString stringWithUTF8String:phoneStr] withAddress:[NSString stringWithUTF8String:addressStr]];
? ? ? ? ? ? [message addObject:lMessage];
? ? ? ? }
? ? ? ? return message;
? ? }
? ? else{
? ? ? NSLog(@"查詢失敗");
? ? }
? ? return nil;
}
- (void)dropTable:(NSString *)table
{
? ? NSString *sql = [NSString stringWithFormat:@"drop table %@",table];
? ? char *error;
? ? int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, &error);
? ? if(result == SQLITE_OK){
? ? ? ? NSLog(@"刪除表成功!");
? ? }
? ? else{
? ? ? ? NSLog(@"刪除表失??!%s",error);
? ? }
? }
//為判斷是否table表已存在。
-(BOOL)checkName:(NSString?*)name{
? ??char?*err;
? ??NSString?*sql = [NSString?stringWithFormat:@"SELECT COUNT(*) FROM sqlite_master where type='table' and name='%@';",name];
? ??const?char?*sql_stmt = [sql?UTF8String];
? ??if(sqlite3_exec(db, sql_stmt,?NULL,?NULL, &err) ==?1){
? ? ? ??return?YES;
? ? }else{
? ? ? ??return?NO;
? ? }
}
!其中model想要輸出對象,要實(shí)現(xiàn)其descripe函數(shù),相當(dāng)于java的tostring。
四,F(xiàn)MDB存儲
sqlite3的封裝,是一個第三方框架,因?yàn)閟qlite3是對語言的封裝,不太方便,所以FMDB就是完全對語言進(jìn)行了oc的封裝。
pod FMDB 此為第三方庫
//頭文件引入#import "fmdb/FMDB.h"
//聲明fmdb的變量
@property (nonatomic,retain) FMDatabase *db;
//在tools工具類中相應(yīng)完成打開數(shù)據(jù)庫,創(chuàng)建table等操作。
//數(shù)據(jù)庫打開之后就要隨時關(guān)閉,否則會浪費(fèi)資源
- (void)createDB
{
//? ? 1,查找沙盒
? ? NSString *str = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES).firstObject;
//? ? 2,拼接數(shù)據(jù)庫
? ? NSString *strDocument = [str stringByAppendingPathComponent:@"Message.db"];
//? ? 3,常用數(shù)據(jù)庫
? ? self.db = [FMDatabase databaseWithPath:strDocument];
? ? BOOL isSuccess = [self.db open];
? ? if(isSuccess){
? ? ? ? NSLog(@"打開成功!");
? ? }else{
? ? ? ? NSLog(@"打開失敗!");
? ? }
}
//跟sqlite3不同的是,這里面要要把變量改成?。在executeUpdate的后面做相應(yīng)的改變。
- (void)createTab
{
? ? [self createDB];
? ? //創(chuàng)建table。
? ? NSString *sql = [NSString stringWithFormat:@"create table message(id integer primary key autoincrement, name text,phone text,address text)"];
? ? BOOL isSuccess = [self.db executeUpdate:sql];
? ? if(isSuccess){
? ? ? ? NSLog(@"table創(chuàng)建成功");
? ? }
? ? else{
? ? ? ? NSLog(@"table創(chuàng)建失敗");
? ? }
? ? [self.db close];
}
//如果有基礎(chǔ)數(shù)據(jù)就直接用@{}轉(zhuǎn)變?yōu)閷ο蟆?/p>
- (void)insertMessage:(LHBMessage *)message
{
? ? [self createDB];
? ? NSString *sql = [NSString stringWithFormat:@"insert into message(name,phone,address) values (?,?,?)"];
? ? BOOL isSuccess = [self.db executeUpdate:sql,message.name,message.phone,message.address];
? ? if(isSuccess){
? ? ? ? NSLog(@"table插入成功");
? ? }
? ? else{
? ? ? ? NSLog(@"table插入失敗");
? ? }
? ? [self.db close];
}
//做相應(yīng)的數(shù)據(jù)庫查詢操作,用到函數(shù)excuteQuery
- (NSArray<LHBMessage *> *)queryMessageByName:(NSString *)name
{
? ? [self createDB];
? ? NSString *sql = [NSString stringWithFormat:@"select * from message where name = ?"];
? ? //sql語句的內(nèi)部結(jié)構(gòu)
? ? NSMutableArray *message = [[NSMutableArray alloc]init];
? //先拿到結(jié)果集
? ? FMResultSet *set = [self.db executeQuery:sql,name];
? ? ? ? while ([set next]) {
? ? ? ? NSString *nameStr = [set stringForColumnIndex:1];
? ? ? ? NSString *phoneStr = [set stringForColumnIndex:2];
? ? ? ? NSString *addressStr = [set stringForColumnIndex:3];
? ? ? ? ? ? LHBMessage *lMessage = [[LHBMessage alloc]initWithObject:nameStr withPhone:phoneStr withAddress:addressStr];
? ? ? ? ? ? [message addObject:lMessage];
? ? ? ? }
? ? [self.db close];
? ? ? ? return message;
}