iOS數(shù)據(jù)存儲(chǔ)通常有以下五種方式:
1、Plist 2、NSUserDefaults 3、NSkeyedArchiver 4、SQLite 5、CoreData
等不及想看項(xiàng)目的同學(xué)點(diǎn)這兒demo
1、Plist
可被序列化的通常有以下幾種類型:
NSString(含NSMutableString),NSArray(含NSMutableArray), NSDictionary(含NSMutableDictionary),NSData(含 NSMutableData),NSNumber,NSDate
使用方法
- 不在工程中新建plist文件
先創(chuàng)建一個(gè)plist的存儲(chǔ)路徑
NSString *docuPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *plistPath = [docuPath stringByAppendingPathComponent:@"hooyking.plist"];
以NSString保存示例
NSError *error = nil;
[@"張三" writeToFile:plistPath atomically:YES encoding:NSUTF8StringEncoding error:&error];
NSString數(shù)據(jù)取出
NSError *error = nil;
NSString *string = [NSString stringWithContentsOfFile:plistPath encoding:NSUTF8StringEncoding error:&error];
-
在工程中新建一個(gè)plist文件
plist.png
以NSArray保存示例
NSString *customerPlistPath = [[NSBundle mainBundle] pathForResource:@"HK" ofType:@"plist"];
NSArray *nameArray = @[@"first",@"last"];
[nameArray writeToFile:customerPlistPath atomically:YES];
NSArray數(shù)據(jù)取出
NSArray *customerPlistArray = [NSArray arrayWithContentsOfFile:customerPlistPath];
NSLog(@"項(xiàng)目中新建的plist文件保存的數(shù)據(jù)%@",customerPlistArray);
2、NSUserDefaults
NSUserDefaults支持的數(shù)據(jù)類型通常有以下幾種:
NSNumber(CGFloat、NSInteger、int、float、double), NSString(含NSMutableString),NSData(含NSMutableData,NSArray(含NSMutableArray),NSDictionary(含NSMutableDictionary),BOOL
- 基本數(shù)據(jù)類型
NSUserDefaults存儲(chǔ)的對(duì)象全是不可變的,即使存進(jìn)去的是可變的,取出來(lái)也是不可變的,如NSMutableArray存進(jìn)去,取出來(lái)就是NSArray了。
以NSString保存示例
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setObject:self.textField.text forKey:@"userDefaultKey"];
[ud synchronize];
NSString數(shù)據(jù)取出
NSString *text = [ud objectForKey:userDefaultKeyStr];
NSLog(@"取出的數(shù)據(jù)%@",text);
- 自定義類型
使用NSUserDefaults保存自定義類型,自定義類型必須遵循NSCoding協(xié)議,下面以PersonModel示例。
PersonModel.h中遵循<NSCoding>

PersonModel.m中實(shí)現(xiàn)解歸檔
//歸檔
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
//解檔
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
保存數(shù)據(jù)
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
PersonModel *model = [PersonModel new];
model.name = @"張哈哈";
model.age = 10;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:model];
[ud setObject:data forKey:@"customerObjectKey"];
[ud synchronize];
取出數(shù)據(jù)
NSData *data = [ud objectForKey:@"customerObjectKey"];
PersonModel *model = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(@"名字:%@--年齡:%zd",model.name,model.age);
3、NSKeyedArchiver
這里的后綴名用了.data,實(shí)際上用什么后綴名都無(wú)所謂的。
- 單個(gè)普通數(shù)據(jù)的歸解檔
文件路徑
NSString *docuPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSLog(@"歸檔文件路徑:%@",docuPath);
NSString *singleCommonFilePath = [docuPath stringByAppendingPathComponent:@"singleCommon.data"];
歸檔
NSString *singleString = @"單個(gè)普通數(shù)據(jù)的歸檔看看如何?";
BOOL singleSuccess = [NSKeyedArchiver archiveRootObject:singleString toFile:singleCommonFilePath];
if (singleSuccess) {
NSLog(@"單個(gè)普通數(shù)據(jù)歸檔成功");
} else {
NSLog(@"單個(gè)普通數(shù)據(jù)歸檔失敗");
}
解檔
NSString *singleString = [NSKeyedUnarchiver unarchiveObjectWithFile:singleCommonFilePath];
NSLog(@"單個(gè)普通數(shù)據(jù)的解檔:%@",singleString);
- 多個(gè)普通數(shù)據(jù)的歸解檔
文件路徑
NSString *docuPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSLog(@"歸檔文件路徑:%@",docuPath);
NSString *multipleCommonFilePath = [docuPath stringByAppendingPathComponent:@"multipleCommon.data"];
歸檔
NSInteger age = 20;
NSString *name = @"張三";
NSArray *toies = @[@"柯尼賽格",@"百達(dá)斐麗",@"陸家嘴100套房"];
NSMutableData *mutableData = [[NSMutableData alloc] init];
NSKeyedArchiver *multipleKeyArchiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mutableData];
[multipleKeyArchiver encodeInteger:age forKey:@"age"];
[multipleKeyArchiver encodeObject:name forKey:@"name"];
[multipleKeyArchiver encodeObject:toies forKey:@"toies"];
[multipleKeyArchiver finishEncoding];//完成歸檔
BOOL multipleSuccess = [mutableData writeToFile:multipleCommonFilePath atomically:YES];//寫入文件
if (multipleSuccess) {
NSLog(@"多個(gè)普通數(shù)據(jù)歸檔成功");
} else {
NSLog(@"多個(gè)普通數(shù)據(jù)歸檔失敗");
}
解檔
NSMutableData *mutableData = [NSMutableData dataWithContentsOfFile:multipleCommonFilePath];
NSKeyedUnarchiver *keyedUnarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:mutableData];
NSInteger age = [keyedUnarchiver decodeIntegerForKey:@"age"];
NSString *name = [keyedUnarchiver decodeObjectForKey:@"name"];
NSArray *toies = [keyedUnarchiver decodeObjectForKey:@"toies"];
[keyedUnarchiver finishDecoding];
NSLog(@"多個(gè)普通數(shù)據(jù)的解檔:年齡:%zd--名字:%@--玩具:%@,%@,%@",age,name,toies[0],toies[1],toies[2]);
- 自定義對(duì)象的歸解檔
自定義對(duì)象的歸檔必須遵循NSCoding協(xié)議,當(dāng)然自定義對(duì)象還可以包含自定義對(duì)象,被包含自定義對(duì)象同樣需要遵循NSCoding協(xié)議,下面以CarModel和EngineModel示例,CarModel包含EngineModel

對(duì)于自定義對(duì)象,不論他是只保存這個(gè)對(duì)象還是對(duì)象的array,dictionary,set,只要此對(duì)象遵循了NSCoding協(xié)議,都可進(jìn)行歸檔
文件路徑
NSString *docuPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSLog(@"歸檔文件路徑:%@",docuPath);
NSString *customerModelFilePath = [docuPath stringByAppendingPathComponent:@"car.data"];
歸檔
CarModel *car = [[CarModel alloc] init];
car.price = 50000000;
car.brand = @"布加迪威龍";
car.wheelArr = @[@"左前輪",@"右前輪",@"左后輪",@"右后輪"];
EngineModel *engine = [[EngineModel alloc] init];
engine.model = @"無(wú)敵旋風(fēng)";
engine.cylinderNumber = 100;
car.engine = engine;
BOOL success = [NSKeyedArchiver archiveRootObject:car toFile:customerModelFilePath];
if (success) {
NSLog(@"自定義對(duì)象歸檔成功");
} else {
NSLog(@"自定義對(duì)象歸檔失敗");
}
解檔
CarModel *car = [NSKeyedUnarchiver unarchiveObjectWithFile:customerModelFilePath];
NSLog(@"自定義對(duì)象的解檔:車價(jià)格:%.2f--車標(biāo):%@--車輪子:%@,%@,%@,%@--發(fā)動(dòng)機(jī)型號(hào):%@--發(fā)動(dòng)機(jī)氣缸數(shù):%zd",
car.price,car.brand,car.wheelArr[0],car.wheelArr[1],car.wheelArr[2],car.wheelArr[3],car.engine.model,car.engine.cylinderNumber);
4.SQLite
SQLite存儲(chǔ)類型通常有以下幾種:
NULL NULL值
REAL 浮點(diǎn)型(如CGFloat,float,double,不過(guò)都需要轉(zhuǎn)成NSNumber存)
INTEGER 整型(如NSInteger,int,不過(guò)都需要轉(zhuǎn)成NSNumber存)
TEXT 文本類(如NSString)
BLOB 二進(jìn)制(如圖片、文件NSData
注意這個(gè)插入的數(shù)據(jù)那些都是對(duì)象,text對(duì)應(yīng)NSString,blob對(duì)應(yīng)NSData,integer對(duì)應(yīng)NSNumber
通常我們不直接使用系統(tǒng)的SQLite,而是用FMDB,它是對(duì)SQLite的封裝,使用更加優(yōu)美。
下面就詳細(xì)說(shuō)說(shuō)FMDB的使用
數(shù)據(jù)庫(kù)路徑及初始化FMDatabase
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSLog(@"documentPath:%@",path);
NSString *dbpath = [path stringByAppendingPathComponent:@"hooyking.db"];
FMDatabase *db = [FMDatabase databaseWithPath:dbpath];
self.myDb = db;
對(duì)表操作后記得一定要調(diào)用close方法
- 創(chuàng)建表
- (void)createTable {
if ([_myDb open]) {
//這兒創(chuàng)建了一個(gè)列有 name|sex|age|nickname|phoneNum|nativePlace|photo 的名字為personTable的表
BOOL result = [_myDb executeUpdate:@"create table if not exists personTable (name text, sex integer, age integer, nickname text, phoneNum text, nativePlace text, photo blob)"];
if (result) {
NSLog(@"創(chuàng)建表成功");
}
else {
NSLog(@"創(chuàng)建表失敗");
}
[_myDb close];
}
}
- 插入數(shù)據(jù)
- (void)insertData {
if ([_myDb open]) {
BOOL result = [_myDb executeUpdate:@"insert into personTable (name, sex, age, nickname, phoneNum, nativePlace, photo) values (?,?,?,?,?,?,?)",@"JDX",[NSNumber numberWithInteger:1],[NSNumber numberWithInteger:18], @"hooyking", [NSNumber numberWithInteger:13888888888],@"sichuan",[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"picture" ofType:@"jpg"]]];
if (result) {
NSLog(@"添加數(shù)據(jù)成功");
}
else {
NSLog(@"添加數(shù)據(jù)失敗");
}
[_myDb close];
}
}
- 刪除數(shù)據(jù)
- (void)deleteData {
//刪除這個(gè)表里nickname為hooyking的所有數(shù)據(jù),列沒(méi)有刪除,依然存在
if ([_myDb open]) {
BOOL result = [_myDb executeUpdate:@"delete from personTable where nickname = ?",@"hooyking"];
if (result) {
NSLog(@"刪除數(shù)據(jù)成功");
}
else {
NSLog(@"刪除數(shù)據(jù)失敗");
}
[_myDb close];
}
}
- 修改數(shù)據(jù)
- (void)updateData {
if ([_myDb open]) {
BOOL result = [_myDb executeUpdate:@"update personTable set age = ? where nickname = ?",[NSNumber numberWithInteger:25],@"hooyking"];
if (result) {
NSLog(@"修改數(shù)據(jù)成功");
}
else {
NSLog(@"修改數(shù)據(jù)失敗");
}
[_myDb close];
}
}
- 查詢數(shù)據(jù)
- (void)selectData {
if ([_myDb open]) {
//查詢多條數(shù)據(jù)
FMResultSet *res = [_myDb executeQuery:@"select name, age from personTable"];
while ([res next]) {
NSString *name = [res stringForColumn:@"name"];
NSInteger age = [res intForColumn:@"age"];
NSLog(@"姓名:%@----年齡:%ld",name,age);
}
//查詢一條數(shù)據(jù)
NSLog(@"年齡為25的人:%@",[_myDb stringForQuery:@"select name from personTable where age = ?",@25]);
[_myDb close];
}
}
- 建多張表,插入,查詢多個(gè)數(shù)據(jù)等
- (void)moreOperate {
if ([_myDb open]) {
//創(chuàng)建表
NSString *createSql = @"create table if not exists studentsTable1 (id integer, name text, sex integer);"
"create table if not exists studentsTable2 (id integer, name text, sex integer);"
"create table if not exists studentsTable3 (id integer, name text, sex integer);";
BOOL createResult = [_myDb executeStatements:createSql];
if (createResult) {
NSLog(@"創(chuàng)建多張表成功");
}
else {
NSLog(@"創(chuàng)建多張表失敗");
}
//*********************************插入多條數(shù)據(jù)(這里涉及到線程安全)**************************************
//**********************方法一*********************
NSString *insertSql = @"insert into studentsTable1 (id, name, sex) values ('100', '張三', '1');"
"insert into studentsTable2 (id, name, sex) values ('200', '李四', '1');"
"insert into studentsTable3 (id, name, sex) values ('300', '如花', '0');";
BOOL insertResult = [_myDb executeStatements:insertSql];
if (insertResult) {
NSLog(@"插入數(shù)據(jù)成功");
}
else {
NSLog(@"插入數(shù)據(jù)失敗");
}
//*********************方法二**********************
//看這個(gè)方法:moreQueue
//查詢數(shù)據(jù)
NSString *selectSql = @"select * from studentsTable1;"
"select * from studentsTable2;"
"select * from studentsTable3;";
BOOL selectResult = [_myDb executeStatements:selectSql withResultBlock:^int(NSDictionary *dictionary) {
NSLog(@"moreOperate查詢到的結(jié)果:%@", [[dictionary allValues] componentsJoinedByString:@","]);
return 0;
}];
if (selectResult) {
NSLog(@"查詢成功");
}
else {
NSLog(@"查詢失敗");
}
[_myDb close];
}
}
- 多個(gè)數(shù)據(jù)插入線程安全
- (void)moreQueue {
//方法二里面線程安全又有兩種方式,ok繼續(xù)看
if ([_myDb open]) {
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *dbpath = [path stringByAppendingPathComponent:@"hooyking.db"];
FMDatabaseQueue *dbQueue = [FMDatabaseQueue databaseQueueWithPath:dbpath];
//第一種(一般就用這種就能保證線程安全了,那條數(shù)據(jù)有錯(cuò),那么有錯(cuò)那條就不會(huì)插入進(jìn)去,例如id改為i,自己看效果)
[dbQueue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"insert into studentsTable1 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:500], @"王五", [NSNumber numberWithInteger:1]];
[db executeUpdate:@"insert into studentsTable2 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:600], @"陸六", [NSNumber numberWithInteger:1]];
[db executeUpdate:@"insert into studentsTable3 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:700], @"史真香", [NSNumber numberWithInteger:0]];
}];
//第二種事務(wù)(當(dāng)插入數(shù)據(jù)有錯(cuò)時(shí),直接取消將插入的數(shù)據(jù),可以改下列試試,例如id改為i,自己看效果)
// [dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
// BOOL res1 = [db executeUpdate:@"insert into studentsTable1 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:500], @"王五", [NSNumber numberWithInteger:1]];
// BOOL res2 = [db executeUpdate:@"insert into studentsTable2 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:600], @"陸六", [NSNumber numberWithInteger:1]];
// BOOL res3 = [db executeUpdate:@"insert into studentsTable3 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:700], @"史真香", [NSNumber numberWithInteger:0]];
// if (!res1 || !res2 || !res3) { //我這樣寫就是三條任何一條有錯(cuò),這三條就一條都不插入,這個(gè)判斷條件若是不寫,那就會(huì)默認(rèn)哪一條有錯(cuò),那一條就不會(huì)加入,但是其他的正確的會(huì)插入
// *rollback = YES;
// }
// [db executeUpdate:@"insert into studentsTable3 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:800], @"你真溜", [NSNumber numberWithInteger:0]];
// }];
//查詢數(shù)據(jù)
NSString *selectSql = @"select * from studentsTable1;"
"select * from studentsTable2;"
"select * from studentsTable3;";
BOOL selectResult = [_myDb executeStatements:selectSql withResultBlock:^int(NSDictionary *dictionary) {
NSLog(@"moreQueue查詢到的結(jié)果:%@", [[dictionary allValues] componentsJoinedByString:@","]);
return 0;
}];
if (selectResult) {
NSLog(@"查詢成功");
}
else {
NSLog(@"查詢失敗");
}
[_myDb close];
}
}
對(duì)列的操作
添加列
- (void)addColumn {
if ([_myDb open]) {
//這兒添加了添加名字為temp類型為text的列
BOOL addColumnRes = [_myDb executeUpdate:@"alter table studentsTable1 add temp text"];
if (addColumnRes) {
NSLog(@"添加列成功");
}
else {
NSLog(@"添加列失敗");
}
[_myDb close];
}
}
刪除列
SQLite不支持alter對(duì)列進(jìn)行修改與刪除的方法來(lái)的,所以要?jiǎng)h除列的替代方式為新建一個(gè)沒(méi)有你要?jiǎng)h除的列的表
第一步:create table testTable(id integer, name text, sex integer);創(chuàng)建一個(gè)新表testTable,這個(gè)表沒(méi)有列temp了;
第二步:insert into testTable select id, name, sex from studentsTable1;這兒完成了將表studentsTable1列id name sex中的全部數(shù)據(jù)插入到了表testTable中;
第三步:drop table if exists studentsTable1;刪除原來(lái)的表studentsTable1;
第四步:alter table testTable rename to studentsTable1;將testTable重命名為studentsTable1,若是你要修改列名,方式和刪除一樣,可自己操作一下。刪除表
- (void)dropTable {
//銷毀這張表(即這個(gè)表刪除后就不存在了)
if ([_myDb open]) {
BOOL result = [_myDb executeUpdate:@"drop table if exists personTable"];
if (result) {
NSLog(@"銷毀表成功");
}
else {
NSLog(@"銷毀表失敗");
}
[_myDb close];
}
}
5、CoreData
新建項(xiàng)目時(shí)可勾選Use Core Data,勾選之后創(chuàng)建的項(xiàng)目就自帶CoreData了

若是不勾選,新建的項(xiàng)目就沒(méi)有CoreData文件,想使用CoreData就要通過(guò)New File選擇Data Model

建好之后為如下圖所示

點(diǎn)擊下方Add Entity添加實(shí)體
這兒我們添加Teacher與Student實(shí)體



右側(cè)Relationship設(shè)置
Properties
transient:設(shè)置當(dāng)前屬性是否只存在于內(nèi)存,不被持久化到本地,如果設(shè)置為YES,關(guān)聯(lián)關(guān)系屬性就不參與持久化操作。transient設(shè)置為YES一般存儲(chǔ)一些在內(nèi)存中緩存的數(shù)據(jù),如存儲(chǔ)臨時(shí)數(shù)據(jù),當(dāng)app殺死后數(shù)據(jù)不會(huì)存在本地,該選項(xiàng)默認(rèn)NO。
optional: 設(shè)置向MOC保存數(shù)據(jù)時(shí),這個(gè)屬性是否必須有值。設(shè)置為NO時(shí),MOC進(jìn)行操作時(shí),若是無(wú)值,會(huì)失敗并返回一個(gè)error,該選項(xiàng)默認(rèn)YES。
Delete Rule
設(shè)置關(guān)聯(lián)屬性的刪除規(guī)則。一共四個(gè)值:這兒一般選后三個(gè)值,當(dāng)選No Action時(shí),Xcode也會(huì)報(bào)警告,讓設(shè)置一個(gè)關(guān)聯(lián)關(guān)系。
No Action:當(dāng)前實(shí)體刪除后對(duì)關(guān)聯(lián)實(shí)體無(wú)任何操作,也不會(huì)將關(guān)聯(lián)對(duì)象的關(guān)聯(lián)屬性指向nil,刪除后使用關(guān)聯(lián)對(duì)象的關(guān)聯(lián)屬性,可能會(huì)導(dǎo)致其他問(wèn)題。
Nullify:刪除后會(huì)將關(guān)聯(lián)實(shí)體的關(guān)聯(lián)屬性指向nil,delete Rule默認(rèn)值。
Cascade:刪除當(dāng)前對(duì)象后,會(huì)將與之關(guān)聯(lián)的實(shí)體也一并刪除。
Deny:在刪除當(dāng)前實(shí)體時(shí),如果當(dāng)前對(duì)象還指向其他關(guān)聯(lián)對(duì)象,則當(dāng)前實(shí)體不能被刪除。
Type
設(shè)置當(dāng)前實(shí)體與關(guān)聯(lián)實(shí)體的關(guān)聯(lián)關(guān)系
To One:當(dāng)前實(shí)體只可持有1個(gè)關(guān)聯(lián)實(shí)體(默認(rèn)值)
To Many:當(dāng)前實(shí)體只可持有多個(gè)關(guān)聯(lián)實(shí)體
Count(只有選擇To Many時(shí)才有)
設(shè)置最小值與最大值,默認(rèn)值不設(shè)置
Minimum:最小值
Maximum:最大值
Advanced
設(shè)置索引
indexed: 設(shè)置當(dāng)前屬性是否是索引。添加索引后可以提升檢索速度,但是對(duì)于刪除操作,刪除索引后其他地方還需要做出相應(yīng)的變化,所以速度會(huì)比較慢,默認(rèn)值NO。
Spotlight
Store in External Record File: 當(dāng)存儲(chǔ)二進(jìn)制文件時(shí),如果遇到比較大的文件,是否存儲(chǔ)在存儲(chǔ)區(qū)之外。如果選擇YES,存儲(chǔ)文件大小超過(guò)1MB的文件,都會(huì)存儲(chǔ)在存儲(chǔ)區(qū)之外。否則大型文件存儲(chǔ)在存儲(chǔ)區(qū)內(nèi),會(huì)造成SQLite進(jìn)行表操作時(shí),效率受到影響,默認(rèn)值NO。
設(shè)置好關(guān)系后創(chuàng)建模型文件
Xcode->Editor->Create NSManageredObject Subclass 勾選兩個(gè)實(shí)體,創(chuàng)建好后會(huì)報(bào)錯(cuò),在如下圖里找到文件,移除后就沒(méi)了

你可以在student屬性里看到如此這般
@property (nullable, nonatomic, retain) NSSet<Teacher *> *teachers;
你可以在Teacher屬性里看到如此這般
@property (nullable, nonatomic, retain) NSSet<Student *> *students;
- 創(chuàng)建CoreData數(shù)據(jù)庫(kù)
- (void)createCoreDataLite {
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreData" withExtension:@"momd"];//CoreData為你自定義的CoreData文件名,momd為固定的類型
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"coreData.sqlite"];
NSLog(@"數(shù)據(jù)庫(kù)地址%@",path);
NSURL *sqlURL = [NSURL fileURLWithPath:path];
NSError *error = nil;
[store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqlURL options:nil error:&error];
if (error) {
NSLog(@"錯(cuò)誤%@",error);
} else {
NSLog(@"創(chuàng)建數(shù)據(jù)庫(kù)成功,如果已添加此數(shù)據(jù)庫(kù),就算再次調(diào)用也不用重復(fù)添加,直接使用以前的");
}
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.persistentStoreCoordinator = store;
self.context = context;
}
- 添加數(shù)據(jù)
- (void)insertData {
Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.context];
student.name = [NSString stringWithFormat:@"Student%d",arc4random()%100];
student.age = arc4random()%20;
student.sex = arc4random()%2 == 0 ? @"女" : @"男";
Teacher *teacher = [NSEntityDescription insertNewObjectForEntityForName:@"Teacher" inManagedObjectContext:self.context];
teacher.name = [NSString stringWithFormat:@"Teacher%d",arc4random()%100];
teacher.age = arc4random()%60;
teacher.students = [NSSet setWithArray:@[student]];
NSError *error = nil;
if ([self.context save:&error]) {
NSLog(@"插入成功");
} else {
NSLog(@"插入失敗");
}
}
- 刪除數(shù)據(jù)
- (void)deleteData {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Teacher"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 50"];
request.predicate = predicate;
NSArray *deleteArray = [self.context executeFetchRequest:request error:nil];
for (Teacher *model in deleteArray) {
NSLog(@"老師的學(xué)生%@",model.students);
[self.context deleteObject:model];
}
NSError *error = nil;
if ([self.context save:&error]) {
NSLog(@"刪除成功");
} else {
NSLog(@"刪除失敗%@",error);
}
}
- 更新數(shù)據(jù)
- (void)updateData {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Teacher"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 45"];
request.predicate = predicate;
NSArray *updateArray = [self.context executeFetchRequest:request error:nil];
for (Teacher *model in updateArray) {
model.name = @"張三";
}
NSError *error = nil;
if ([self.context save:&error]) {
NSLog(@"更新成功");
} else {
NSLog(@"更新失敗");
}
}
- 查詢數(shù)據(jù)
- (void)findData {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Teacher"];
//此處可寫查詢條件(更多條件設(shè)定可瀏覽器自行搜索)
// NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 50"];
// request.predicate = predicate;
//此處可寫排序條件(這兒按年齡排序)
// NSSortDescriptor *ageSort = [NSSortDescriptor sortDescriptorWithKey:@"age"ascending:YES];
// request.sortDescriptors = @[ageSort];
NSArray *resultArray = [self.context executeFetchRequest:request error:nil];
self.dataMArray = [resultArray mutableCopy];
[self.tableView reloadData];
}
