iOS的數據存儲是iOS應用開發的重要知識點:
關於這方面知識,網上有很多介紹,但對於代碼層次的使用方式並未有系統全面介紹。此文章針對iOS稍熟悉的童鞋,需要對CoreData的原理有一定的了解。目前存儲方式大概有以下幾種:
NSKeyedArchiver 適用簡單數據加密NSUserDefaults 適用配置參數Write 文件操作,同NSKeyedArchiverSQLite3 操作較復雜,不建議使用。CoreData 取代SQLite3,但要遵循NSManagedObjectContext基本規則。UT代碼確保使用方式正確。請閱讀以下內容:
#import#import #import "CoreDataHelper.h" @interface StudyUITests : XCTestCase @end @implementation StudyUITests - (void)setUp { [super setUp]; } - (void)tearDown { [super tearDown]; } -(void)testCoreData{ CoreDataHelper *coreHelper = [[CoreDataHelper alloc] init]; [coreHelper coreDataTest]; } -(void)testSqlite3{ sqlite3 *db; NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *databasePath = [documentPath stringByAppendingPathComponent:@"test.sqlite"]; NSLog(@"db path: %@",databasePath); if(sqlite3_open([databasePath UTF8String], &db) != SQLITE_OK){ sqlite3_close(db); NSLog(@"open sqlite fail!"); NSAssert(FALSE, @"create sqlite error"); } NSString *sqlCreateTable = @"CREATE TABLE IF NOT EXISTS ptable (ID INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, address TEXT)"; char *error; if(sqlite3_exec(db, [sqlCreateTable UTF8String], NULL, NULL, &error) != SQLITE_OK){ sqlite3_close(db); NSLog(@"can not create table."); NSAssert(FALSE, @"create table error"); } NSString *deleteAllSql = @"delete from ptable"; if(sqlite3_exec(db, [deleteAllSql UTF8String], NULL, NULL, &error) != SQLITE_OK){ sqlite3_close(db); NSLog(@"delete values from table"); NSAssert(FALSE, @"delete values from table"); } NSString *sql1 = [NSString stringWithFormat: @"INSERT INTO '%@' ('%@', '%@', '%@') VALUES ('%@', '%@', '%@')", @"ptable", @"name", @"age", @"address", @"first name", @"23", @"pukou"]; NSString *sql2 = [NSString stringWithFormat: @"INSERT INTO '%@' ('%@', '%@', '%@') VALUES ('%@', '%@', '%@')", @"ptable", @"name", @"age", @"address",@"second name", @"20", @"qixia"]; if(sqlite3_exec(db, [sql1 UTF8String], NULL, NULL, &error) != SQLITE_OK){ sqlite3_close(db); NSLog(@"can not insert sql1"); NSAssert(FALSE, @"create insert db (sql1) error"); } if(sqlite3_exec(db, [sql2 UTF8String], NULL, NULL, &error) != SQLITE_OK){ sqlite3_close(db); NSLog(@"can not insert sql2"); NSAssert(FALSE, @"create insert db (sql2) error"); } //Read data and check result. NSString *query = @"select * from ptable"; sqlite3_stmt *statement; if(sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, nil) == SQLITE_OK){ //start to traverse data int size = 0; while (sqlite3_step(statement) == SQLITE_ROW) { size++; char *name = (char*)sqlite3_column_text(statement, 1); int age= (int)sqlite3_column_int(statement, 2); char *address = (char*)sqlite3_column_text(statement, 3); NSString *nameStr = [[NSString alloc] initWithUTF8String:name]; NSString *addressStr = [[NSString alloc] initWithUTF8String:address]; NSLog(@"name: %@ age: %d address: %@",nameStr,age,addressStr); } NSAssert(size == 2, @"size should 2"); }else{ NSAssert(FALSE, @"query db error"); } sqlite3_close(db); } -(void)testWriteToFile{ NSString *st1 = @"first"; NSString *st2 = @"second"; NSArray *array = [NSArray arrayWithObjects:st1,st2, nil]; NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSAssert(path != nil, @"path is nil"); NSString *filename = [path stringByAppendingPathComponent:@"test.data"]; NSAssert([array writeToFile:filename atomically:YES],@"write successfully"); NSMutableArray *savearray = [NSMutableArray arrayWithContentsOfFile:filename]; NSAssert([[savearray objectAtIndex:0] isEqualToString:st1], @"not equal to str1"); NSAssert([[savearray objectAtIndex:1] isEqualToString:st2], @"not equal to str2"); } -(void)testUserDefault{ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *name = @"test"; [defaults setObject:name forKey:@"name"]; UIImage *image = [UIImage imageNamed:@"photo"]; NSData *imageData = UIImagePNGRepresentation(image); [defaults setObject:imageData forKey:@"image"]; //now read from data NSString *name1= [defaults objectForKey:@"name"]; NSData *imageData1 = [defaults objectForKey:@"image"]; NSAssert([name1 isEqualToString:name], @"name1 is equal to test"); NSAssert([imageData1 isEqualToData:imageData], @"image data is not equal"); } -(void)testKeyedArchiver{ NSString *save1 =@"test1"; NSString *save2 =@"test2"; NSArray *array = [NSArray arrayWithObjects:save1, save2, nil]; NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSString *filename = [path stringByAppendingPathComponent:@"savedatatest"]; NSLog(@"filename : %@",filename); //save data NSAssert([NSKeyedArchiver archiveRootObject:array toFile:filename],@"archive successfully."); array = [NSKeyedUnarchiver unarchiveObjectWithFile:filename]; save1 = [array objectAtIndex:0]; NSAssert([save1 isEqualToString:@"test1"], @"save1 must equals to test1"); save2 = [array objectAtIndex:1]; NSAssert([save2 isEqualToString:@"test2"], @"save1 must equals to test2"); } @end
#import "CoreDataHelper.h" #import#import "Entity.h" @interface CoreDataHelper() @property (strong, nonatomic) NSManagedObjectModel *managedObjectModel; @property (strong, nonatomic) NSManagedObjectContext *managedObjectContext; @property (strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; -(NSPersistentStoreCoordinator *)persistentStoreCoordinator; -(NSManagedObjectContext *)managedObjectContext; -(NSManagedObjectModel *)managedObjectModel; @end @implementation CoreDataHelper -(void)coreDataTest{ NSError *error = nil; NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Entity" inManagedObjectContext:self.managedObjectContext]; NSFetchRequest *request = [[NSFetchRequest alloc] init]; [request setEntity:entityDescription]; NSArray *oldResult = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; for (Entity *bb in oldResult) { [self.managedObjectContext deleteObject:bb]; } NSAssert([self.managedObjectContext save:&error], @"deleting....."); /******insert *****/ Entity *entity = [[Entity alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:nil]; entity.name = @"test"; entity.age = [NSNumber numberWithInt:20]; entity.address = @"beijing"; [self.managedObjectContext insertObject:entity]; NSAssert([self.managedObjectContext save:&error], @"inserting....."); /*****query *****/ NSSortDescriptor *sortDescription = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:NO]; NSArray *sortDescriptions = [[NSArray alloc] initWithObjects:sortDescription, nil]; [request setSortDescriptors:sortDescriptions]; NSMutableArray *array = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; for (Entity *bb in array) { NSLog(@"name: %@ age:%@ address:%@",bb.name,bb.age,bb.address); } NSAssert([array count] == 1, @"count size is equal to 1"); /***** update and check****/ NSArray *updateResult = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; Entity *first = [updateResult objectAtIndex:0]; first.name = @"one"; NSAssert([self.managedObjectContext save:&error], @"updating....."); updateResult = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; first = [updateResult objectAtIndex:0]; NSAssert([first.name isEqualToString:@"one"], @"need to equeal one"); /**** insert and check ****/ entity = [[Entity alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:nil]; entity.name = @"test2"; entity.age = [NSNumber numberWithInt:23]; entity.address = @"nanjing"; [self.managedObjectContext insertObject:entity]; NSAssert([self.managedObjectContext save:&error], @"inserting....."); array = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; for (Entity *bb in array) { NSLog(@"name: %@ age:%@ address:%@",bb.name,bb.age,bb.address); } NSAssert([array count] == 2, @"now size is equal to 2"); } -(NSPersistentStoreCoordinator *)persistentStoreCoordinator{ if(_persistentStoreCoordinator) return _persistentStoreCoordinator; NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSURL *storeURL = [NSURL fileURLWithPath:[documentPath stringByAppendingPathComponent:@"person.sqlite"]]; NSError *error = nil; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if(![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]){ NSLog(@"persistent error : %@",[error userInfo]); } return _persistentStoreCoordinator; } -(NSManagedObjectContext *)managedObjectContext{ if(_managedObjectContext) return _managedObjectContext; NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if(coordinator){ _managedObjectContext = [[NSManagedObjectContext alloc] init]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; } -(NSManagedObjectModel *)managedObjectModel{ if(_managedObjectModel) return _managedObjectModel; NSURL *modeUrl = [[NSBundle mainBundle] URLForResource:@"Entity" withExtension:@"momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modeUrl]; return _managedObjectModel; } @end