數(shù)據(jù)存儲--簡易數(shù)據(jù)存儲
數(shù)據(jù)持久化
1.本地:文件 NSHomeDirectory() / Documents;數(shù)據(jù)庫
2.云端:iCloud (文件,Key-Value數(shù)據(jù)庫);第三方
NSData
Cocoa提供用來表示通用數(shù)據(jù):
讀、寫、訪問
圖片
->創(chuàng)建 UIImage 對象
-->文件 - bundle
-->NSData
-->CGContext
- CGImageRef CGBitmapContextCreateImage(ctx);
->保存 UIImage 對象
-->via data
- NSData * UIImagePNGRepresentation (UIImage *image);
- NSData * UIImageJPEGRepresentation (UIImage *image, CGFloat compressionQuality);
NSString 與存儲
->文本讀寫
->文件路徑處理
Key Value數(shù)據(jù)
->讀
+(NSDictionary<KeyType, ObjectType> *) dictionaryWithContentsOfFile:(NSString *)
+ (NSDictionary<KeyType, ObjectType> *) dictionaryWithContentsOfURL:(NSURL *)
->寫
- (BOOL)writeToFile:(NSString *) atomically:(BOOL)
- (BOOL)writeToURL:(NSURL *) atomically:(BOOL)
配置參數(shù)
->用來保存默認值
-->經(jīng)常變的用自己的UI,不常改的放 settings bundle
-->Domian:
- NSArgumentDomain:Xcode.app/Contents/MacOSX/Xcode -IndexOnOpen NO
- Application:NSUserDefaults
- NSGlobalDomain:defaults read NSGlobalDomain
- Languages:AppleLanguage指定用戶使用的語言
- NSRegistrationDomain:[NSUserDefaults registerDefaults:]提供的默認值
->Mac OS X的defaults命令
defaults read <domain>[key]
defaults find Xcode.IDE
NSUserDefaults
->訪問
[NSUserDefaults standardUserDefaults] //本地
[NSUbiquitousKeyValueStore defaultStore] //iCloud
->登記默認值
- [NSUserDefaults registerDefaults:dict];
->訪問
讀:
-<type>ValueForKey:
寫:
-set<Type>:forKey:
Settings Bundle
->Settings.bundle in app root
->Access via standardDefaults
沙盒、文件與對象歸檔
沙盒機制(SandBox)是一種安全體系,它規(guī)定了應(yīng)用程序只能在為該應(yīng)用創(chuàng)建的文件夾內(nèi)讀取文件,不可以訪問其他地方的內(nèi)容。所有的非代碼文件都保存在這個地方,比如圖片、聲音、屬性列表和文本文件等。
1.每個應(yīng)用程序都在自己的沙盒內(nèi)
2.不能隨意跨越自己的沙盒去訪問別的應(yīng)用程序沙盒的內(nèi)容
3.應(yīng)用程序向外請求或接收數(shù)據(jù)都需要經(jīng)過權(quán)限認證

MyApp.app
①存放內(nèi)容
該目錄包含了應(yīng)用程序本身的數(shù)據(jù),包括資源文件和可執(zhí)行文件等。程序啟動以后,會根據(jù)需要從該目錄中動態(tài)加載代碼或資源到內(nèi)存,這里用到了lazy loading的思想。
②整個目錄是只讀的
為了防止被篡改,應(yīng)用在安裝的時候會將該目錄簽名。非越獄情況下,該目錄中內(nèi)容是無法更改的;在越獄設(shè)備上如果更改了目錄內(nèi)容,對應(yīng)的簽名就會被改變,這種情況下蘋果官網(wǎng)描述的后果是應(yīng)用程序?qū)o法啟動,我沒實踐過。
③是否會被iTunes同步
否
Documents
①存放內(nèi)容
我們可以將應(yīng)用程序的數(shù)據(jù)文件保存在該目錄下。不過這些數(shù)據(jù)類型僅限于不可再生的數(shù)據(jù),可再生的數(shù)據(jù)文件應(yīng)該存放在Library/Cache目錄下。
②是否會被iTunes同步
是
Documents/Inbox
①存放內(nèi)容
該目錄用來保存由外部應(yīng)用請求當(dāng)前應(yīng)用程序打開的文件。
比如我們的應(yīng)用叫A,向系統(tǒng)注冊了幾種可打開的文件格式,B應(yīng)用有一個A支持的格式的文件F,并且申請調(diào)用A打開F。由于F當(dāng)前是在B應(yīng)用的沙盒中,我們知道,沙盒機制是不允許A訪問B沙盒中的文件,因此蘋果的解決方案是講F拷貝一份到A應(yīng)用的Documents/Inbox目錄下,再讓A打開F。
②是否會被iTunes同步
是
Library
①存放內(nèi)容
蘋果建議用來存放默認設(shè)置或其它狀態(tài)信息。
②是否會被iTunes同步
是,但是要除了Caches子目錄外
Library/Caches
①存放內(nèi)容
主要是緩存文件,用戶使用過程中緩存都可以保存在這個目錄中。前面說過,Documents目錄用于保存不可再生的文件,那么這個目錄就用于保存那些可再生的文件,比如網(wǎng)絡(luò)請求的數(shù)據(jù)。鑒于此,應(yīng)用程序通常還需要負責(zé)刪除這些文件。
②是否會被iTunes同步
否。
Library/Preferences
①存放內(nèi)容
應(yīng)用程序的偏好設(shè)置文件。我們使用NSUserDefaults寫的設(shè)置數(shù)據(jù)都會保存到該目錄下的一個plist文件中,這就是所謂的寫道plist中!
②是否會被iTunes同步
是
tmp
①存放內(nèi)容
各種臨時文件,保存應(yīng)用再次啟動時不需要的文件。而且,當(dāng)應(yīng)用不再需要這些文件時應(yīng)該主動將其刪除,因為該目錄下的東西隨時有可能被系統(tǒng)清理掉,目前已知的一種可能清理的原因是系統(tǒng)磁盤存儲空間不足的時候。
②是否會被iTunes同步
否
獲取主要目錄路徑方式:
1.沙盒
NSLog(@"%@",NSHomeDirectory());
2.tmp
NSLog(@"%@",NSTemporaryDirectory());
3.Myapp.app
NSLog(@"%@",[[NSBundle mainBundle] bundlePath]);
4.Documents
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSLog(@"%@",path);
iTunes File Sharing
Info.plist
<key>UIFileSharingEnabled</key>
應(yīng)用間共享文件
->用戶授權(quán) + 操作系統(tǒng)代為操作
-->本機 “Open in”
- UIDocumentInteractionController
-->iCloud
- UIDocumentPickerViewController
對象歸檔
encoder,decoder
NSEncoding protocol
1.保存數(shù)據(jù)過程
//1.創(chuàng)建對象
YYstudent *s=[[YYstudent alloc]init];
s.name=@"wendingding";
s.age=23;
s.height=1.7;
s.weight=62;
//2.獲取文件路徑
NSString *docPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *path=[docPath stringByAppendingPathComponent:@"person.yangyang"];
NSLog(@"path=%@",path);
//3.將自定義的對象保存到文件中
[NSKeyedArchiver archiveRootObject:s toFile:path];
2.讀取數(shù)據(jù)過程
//1.獲取文件路徑
NSString *docPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *path=[docPath stringByAppendingPathComponent:@"person.yangyang"];
//2.從文件中讀取對象
YYstudent *s=[NSKeyedUnarchiver unarchiveObjectWithFile:path];
3.遵守NSCoding協(xié)議,并實現(xiàn)該協(xié)議中的兩個方法。
4.如果是繼承,則子類一定要重寫那兩個方法。因為person的子類在存取的時候,會去子類中去找調(diào)用的方法,沒找到那么它就去父類中找,所以最后保存和讀取的時候新增加的屬性會被忽略。需要先調(diào)用父類的方法,先初始化父類的,再初始化子類的。
5.保存數(shù)據(jù)的文件的后綴名可以隨意命名。
6.通過plist保存的數(shù)據(jù)是直接顯示的,不安全。通過歸檔方法保存的數(shù)據(jù)在文件中打開是亂碼的,安全。
SQLite3
SQLite是一款輕型的嵌入式數(shù)據(jù)庫,安卓和ios開發(fā)使用的都是SQLite數(shù)據(jù)庫。3是版本號,是SQLite的第三個版本。
特點:
1)它占用資源非常的低,在嵌入式設(shè)備中,可能只需要幾百K的內(nèi)存就夠了
2)它的處理速度比Mysql、PostgreSQL這兩款著名的數(shù)據(jù)庫都還快
數(shù)據(jù)庫存儲數(shù)據(jù)的步驟
1、新建一個數(shù)據(jù)庫
2、新建一張表(table)
3、添加多個字段(column,列,屬性)
4、添加多行記錄(row,每行存放多個字段對應(yīng)的值)
數(shù)據(jù)操作語句(DML:Data Manipulation Language) 包括insert、update、delete等操作 上面的3種操作分別用于添加、修改、刪除表中的數(shù)據(jù)。
數(shù)據(jù)查詢語句(DQL:Data Query Language) 可以用于查詢獲得表中的數(shù)據(jù) 關(guān)鍵字select是DQL(也是所有SQL)用得最多的操作 其他DQL常用的關(guān)鍵字有where,order by,group by和having。
SQLite的字段類型 integer : 整型值 real : 浮點值 text : 文本字符串 blob : 二進制數(shù)據(jù)(比如文件) 實際上SQLite是無類型的,但為了保持良好的編程規(guī)范,方便程序員之間的交流,編寫建表語句的時候最好還是加上每個字段的具體類型。
在iOS中使用 SQLite
->鏈接 libSQLite3.dylib和導(dǎo)入頭文件#import
->使用SQLite3函數(shù)
-->打開/新建數(shù)據(jù)庫文件
// 拼接數(shù)據(jù)庫地址
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *sqlFile = [path stringByAppendingPathComponent:@student.sqlite];
// 打開數(shù)據(jù)
int result = sqlite3_open(sqlFile.UTF8String, &_db);
// 判斷是否打開成功
if (result == SQLITE_OK) {
NSLog(@打開成功);
// 創(chuàng)建表
/*
第一個參數(shù): 需要執(zhí)行SQL語句的數(shù)據(jù)庫對象
第二個參數(shù): 需要執(zhí)行的SQL語句
第三個參數(shù): 回調(diào)函數(shù)
第四個參數(shù): 第三個參數(shù)的參數(shù)
第五個參數(shù): 接收錯誤信息
*/
// 創(chuàng)建表的sql語句
NSString *sql = @CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT , name TEXT, age INTEGER, score REAL);;
result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
if (result == SQLITE_OK) {
NSLog(@創(chuàng)建表成功);
}else
{
NSLog(@創(chuàng)建表失敗);
}
}else
{
NSLog(@打開失敗);
}
-->執(zhí)行SQL命令
2、插入數(shù)據(jù)
NSString *sql = @INSERT INTO t_student(age, score, name) VALUES ('28', 100, 'leo');;
int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
if (result == SQLITE_OK) {
NSLog(@插入成功);
}
3、修改數(shù)據(jù)
NSString *sql = @UPDATE t_student SET name = 'txt';;
int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
if (result == SQLITE_OK) {
NSLog(@修改成功);
}
4、刪除數(shù)據(jù)
NSString *sql = @DELETE FROM t_student WHERE id = 1; ;
int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
if (result == SQLITE_OK) {
NSLog(@刪除成功);
}
5、查詢數(shù)據(jù)
NSString *sql = @SELECT * FROM t_student;;
sqlite3_stmt *stemt = NULL;
/*
第一個參數(shù):需要執(zhí)行SQL語句的數(shù)據(jù)庫
第二個參數(shù):需要執(zhí)行的SQL語句
第三個參數(shù): 告訴系統(tǒng)SQL語句的長度, 如果傳入一個小于0的數(shù), 系統(tǒng)會自動計算
第四個參數(shù):結(jié)果集, 里面存放所有查詢到的數(shù)據(jù)
*/
sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stemt, NULL);
// 判斷有沒有查詢結(jié)果
while (sqlite3_step(stemt) == SQLITE_ROW) {
// 取出第一個字段的查詢得結(jié)果
const unsigned char *name = sqlite3_column_text(stemt, 1);
// 取出第一個字段的查詢得結(jié)果
int age = sqlite3_column_int(stemt, 2);
// 取出第一個字段的查詢得結(jié)果
double score = sqlite3_column_double(stemt, 3);
NSLog(@%s %d %f, name, age, score);
}
-->關(guān)閉數(shù)據(jù)庫
sqlite3_close(database);
Core Data
Apple提供的對象持久化框架。使用數(shù)據(jù)庫作為底層存儲,也可以使用XML文件。
CoreData中有這么幾個常用的元素:
名稱 作用
NSManagedObjectModel 對象模型,指定所用對象文件
NSPersistentStoreCoordinator 持久化存儲協(xié)調(diào)器,設(shè)置對象的存儲方式和數(shù)據(jù)存放位置
NSManagedObjectContext 對象管理上下文,負責(zé)數(shù)據(jù)的實際操作(重要)
NSEntityDescriptor 實體描述符,描述一個實體,可以用來生成實體對應(yīng)的對象
NSManagedObject 對象
NSFetchRequest 對象查詢,相當(dāng)于SQL的Select語句
使用步驟
在創(chuàng)建項目的時候,勾選“Core Data”選項。Xcode會自動替我們
在“AppDelegate”中加入創(chuàng)
建“NSManagedObjectModel”、“NSPersistentStoreCoordinator”和“
NSManagedObjectContext”等對象,方便后面的使用。
1.創(chuàng)建"NSManagedObjectModel"對象
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
//CoreData模型文件的路徑,注意編譯好的模型文件名擴展名為"momd"
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreData01" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
2.創(chuàng)建"NSPersistentStoreCoordinator"對象
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
//指定需要持久化的模型對象
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
//持久化的存儲文件
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreData01.sqlite"];
NSError *error = nil;
//設(shè)置存儲格式為SQLite
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
}
return _persistentStoreCoordinator;
}
3.創(chuàng)建上下文
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
//創(chuàng)建管理上下文
_managedObjectContext = [[NSManagedObjectContext alloc] init];
//關(guān)聯(lián)上下文與存儲對象
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
4 . 設(shè)置模型文件,添加實體(Entity)
點擊“CoreData01.xcdatamodelId”文件,然后添加一個實體“Student”,并增加幾個屬性。Core Data中的實體類似于數(shù)據(jù)庫的表定義,規(guī)定了不同字段(屬性)的名字和類型。
5 . 創(chuàng)建模型對象的類, "Editor > Create NSManagedobject Subclass"。
6 . 選擇使用標(biāo)量定義數(shù)值類型的屬性(默認使用NSNumber類型定義int、float等類型的屬性)。
7 . Xcode自動創(chuàng)建于實體同名的類,并且繼承自“NSManagedObject”。
8 . 創(chuàng)建對象并存儲。
//獲取AppDelegate中創(chuàng)建的上下文對象
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = appDelegate.managedObjectContext;
//獲取實體描述符
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];
//創(chuàng)建對象
Student *student = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
//設(shè)置對象的屬性
student.name = @"張三";
//保存數(shù)據(jù)
[context save:nil];
9 . 可以通過"NSFetchRequest"從文件中獲取數(shù)據(jù)。
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = appDelegate.managedObjectContext;
//創(chuàng)建請求對象,用于獲取實體Student所對應(yīng)的全部數(shù)據(jù),可以通過給NSFetchRequest設(shè)置predicate和sortDescriptors對結(jié)果進行篩選和排序。
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
NSArray *result = [context executeFetchRequest:fetchRequest error:nil];
NSLog(@"%@", result);