iOSの3種類のデータストレージとメリット

9405 ワード

1.第1のデータ格納方式:NSKeyedArchiver(アーカイブ)、アーカイブにより直接オブジェクトを格納する
NSCodingプロトコルを遵守し、対応する方法を実現すれば、そのオブジェクトまたはそのオブジェクトを含む他のオブジェクトを直接ファイルに格納することができ、比較的簡単に使用でき、格納時は上書き格納であり、取り出し時も一度にすべてのファイルの内容を取り出すので、多くのデータであれば、アーカイブ方式で比較的リソースを消費し、あまり適切ではありませんが、小型データでなければ、オブジェクト格納などでアーカイブ方式を使用することができます
  • 1.0、アーカイブ方式で保存する必要があるオブジェクトはNSCodingプロトコルを遵守しなければならず、以下のように内部方法を実現しなければならない:
  • // ( )
    - (void)encodeWithCoder:(NSCoder *)aCoder{
        [aCoder encodeObject:_name forKey:@"name"];
        [aCoder encodeInteger:_age forKey:@"age"];
    }
    // ( )
    - (instancetype)initWithCoder:(NSCoder *)aDecoder{
        self = [super init];
        if (self) {
            self.name = [aDecoder decodeObjectForKey:@"name"];
            self.age = (int)[aDecoder decodeIntegerForKey:@"age"];
        }
        return self;
    }
    
    
  • 1.1オブジェクトをファイル
  • にアーカイブする
    // ( : , NSCoding , )
    [NSKeyedArchiver archiveRootObject:dog toFile:@"/users/feng/desktop/dogs.plist"];
    
  • 1.2ファイルからアーカイブを解除し、オブジェクト
  • を得る.
    // , 
    IMDog *dog01 = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/users/feng/desktop/dogs.plist"];
    NSLog(@"%@", dog01);
    
  • 1.3、拡張して、複数のデータの記憶を行って、直接配列の中で行うことができて、以下の通りです:
  • //NSKeyedArchiver( ) : n 
    NSMutableArray *dogsArray = [NSMutableArray array];
    for (int i=0; i<100; i++) {
        NSString *name = [NSString stringWithFormat:@"zhang-%d",i];
        int age = arc4random_uniform(100);
        IMDog *dog = [IMDog dogWithName:name age:age];
        [dogsArray addObject:dog];
    }
    
    // 
    [NSKeyedArchiver archiveRootObject:dogsArray toFile:@"/users/feng/desktop/dogsArray.plist"];
    
    // 
    NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithFile:@"users/feng/desktop/dogsArray.plist"];
    // : 10-20 
    NSArray *result = [array subarrayWithRange:NSMakeRange(10, 10)];
    
    [result enumerateObjectsUsingBlock:^(IMDog *dog, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"name:%@---age:%d", dog.name, dog.age);
    }];
     
    

    2,sqlストレージ(FMDBフレームワーク):
    fmdbフレームワークはsqlのパッケージであり、大型データ記憶に適しており、読み取りフィルタリングが便利で、リソースの消費が少ないが、sqlは直接オブジェクトを記憶することができず、オブジェクトをnscodingでバイナリデータに変換して記憶することができる.
    *2.1、普通型データを一つずつ挿入する:
    //1, 
    _db = [FMDatabase databaseWithPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"dogs.sqlite"]];
    [_db open];
    
    //2,  
    [_db executeUpdate:@"create table if not exists t_dogs (id integer primary key, name text, age integer);"];
    
    //3, 
    for (int i=0; i<100; i++) {
        NSString *name = [NSString stringWithFormat:@"zhang-%d",i];
        int age = arc4random_uniform(100);
        [_db executeUpdateWithFormat:@"insert into t_dogs (name, age) values (%@,%d);",name, age];
    }
    
    
    //4, 
    FMResultSet *resultRet = [_db executeQuery:@"select * from t_dogs where age > 30"];
    while (resultRet.next) {
        NSString *name = [resultRet stringForColumn:@"name"];
        //age int , stringForColumn: , ,sql 
        NSString *age = [resultRet stringForColumn:@"age"];
        NSLog(@"%@@@@---@@@%@", name, age);
    }
    
  • 2.2,オブジェクトタイプを1つずつ挿入する:(実際には以前のマイクロブログストレージも1つずつ格納されていた.1つのマイクロブログストレージであるため、すべてのマイクロブログを1つの配列に格納するわけではない):まずオブジェクトをバイナリデータ
  • に変換する必要がある.
    //1, 
    _db = [FMDatabase databaseWithPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"dogsObject.sqlite"]];
    [_db open];
    
    //2,  ( age )
    [_db executeUpdate:@"create table if not exists t_dogs (id integer primary key, dog blob not null, age integer not null);"];
    
    //3, 
     for (int i=0; i<100; i++) {
         NSString *name = [NSString stringWithFormat:@"zhang-%d",i];
         int age = arc4random_uniform(100);
         IMDog *dog = [IMDog dogWithName:name age:age];
         
         NSData *dogData = [NSKeyedArchiver archivedDataWithRootObject:dog];
         
         [_db executeUpdateWithFormat:@"insert into t_dogs (dog, age) values (%@,%d);", dogData, age];
     }
    
    
    //4, 
    FMResultSet *resultRet = [_db executeQuery:@"select * from t_dogs where age > 30"];
    while (resultRet.next) {
        
        NSData *dogData = [resultRet dataForColumn:@"dog"];
        IMDog *dog = [NSKeyedUnarchiver unarchiveObjectWithData:dogData];
    
        NSLog(@"%@@@@---@@@%d", dog.name, dog.age);
    }
    

    *2.3,オブジェクトを配列に入れて一括保存する
  • 配列をバイナリデータ記憶
  • に変換する必要がある.
  • この方法は記憶が便利であるが、取り出すときに対応するソートができない.実は、マイクロブログプロジェクトの記憶は2番目の状況に属するべきである.それはバイナリデータを記憶しているが、すべてのマイクロブログを一緒に記憶しているわけではない.1つのマイクロブログが1つのバイナリデータに変換されて記憶されているからである.
  • //1, 
    _db = [FMDatabase databaseWithPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"dogs_extension.sqlite"]];
    [_db open];
    
    //2,  
    [_db executeUpdate:@"create table if not exists t_dogs (id integer primary key, dogs blob not null);"];
    
    //3, 
    NSMutableArray *dogs = [NSMutableArray array];
    for (int i=0; i<100; i++) {
        NSString *name = [NSString stringWithFormat:@"zhang-%d",i];
        int age = arc4random_uniform(100);
        IMDog *dog = [IMDog dogWithName:name age:age];
        [dogs addObject:dog];
    }
    
    // 
    NSData *dogsData = [NSKeyedArchiver archivedDataWithRootObject:dogs];
    [_db executeUpdateWithFormat:@"insert into t_dogs (dogs) values (%@);",dogsData];
      
    
    //4, 
    FMResultSet *resultRet = [_db executeQuery:@"select * from t_dogs"];
    while (resultRet.next) {
        
        NSData *dogsData = [resultRet objectForColumnName:@"dogs"];
        NSArray *dogArray = [NSKeyedUnarchiver unarchiveObjectWithData:dogsData];
        
        [dogArray enumerateObjectsUsingBlock:^(IMDog *dog, NSUInteger idx, BOOL * _Nonnull stop) {
            NSLog(@"%@---%d",dog.name, dog.age);
        }];
    }
    
  • 2.4、データを削除(sql文を1つ実行すればよい)
  • //5, 
    [_db executeUpdate:@"delete from t_dogs where age > 60"];
    

    3,coreDataストレージ:
    coreDataはiOS独自のデータ格納方式であり、アップルによるsqlのカプセル化であり、直接オブジェクト保存操作が可能な利点がある(オブジェクトを直接保存できるとは言えないが、直接オブジェクトを操作でき、オブジェクトを保存するのが便利である)、個人的には作成が面倒であり、sqlに比べて効率が低い可能性がある.本質はsql文を自動的に生成することである
  • 以前の記事でCoreDataについて紹介したことがありますが、ここでもう一度復習してみましょう.
  • まず、オブジェクトを作成するときはallocではなく、initではなく、次のようにします.
    Dogs *dog = [NSEntityDescription insertNewObjectForEntityForName:@"Dogs" inManagedObjectContext:_context];
    
  • 3.1,CoreDataの作成
  • //1, , 
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"Dogs" withExtension:@"momd"];
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
    
    //2,  , 
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"Dogs.sqlite"];
    NSURL *url01 = [NSURL fileURLWithPath:path];// 
    
    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url01 options:nil error:nil];
    
    //3, , 
    _context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _context.persistentStoreCoordinator = coordinator;
    
  • 3.2、挿入データ
  • //4, ( )
    // 
    Dogs *dog = [NSEntityDescription insertNewObjectForEntityForName:@"Dogs" inManagedObjectContext:_context];
    dog.name = @"zhangdanfeng";
    dog.age = @20;
    
    NSError *error;
    [_context save:&error];
    if (!error) {
        NSLog(@"dog ");
    }
    
    // 
    for (int i=0; i<100; i++) {
        Dogs *dog = [NSEntityDescription insertNewObjectForEntityForName:@"Dogs" inManagedObjectContext:_context];
        dog.name = [NSString stringWithFormat:@"zhangdanfeng--%d",i];
        dog.age = @(arc4random_uniform(100));
        NSError *error;
        [_context save:&error];
        if (!error) {
            NSLog(@" ");
        }
    }
    
  • 3.3、データ/クエリーデータ
  • を読み出す
    //5, 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Dogs"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age > 30"];
    request.predicate = predicate;
    
    NSError *error;
    NSArray *array = [_context executeFetchRequest:request error:&error];
    if (!error) {
        NSLog(@" ");
    }
    
    [array enumerateObjectsUsingBlock:^(Dogs *dog, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"%@!!!!!!%@",dog.name, dog.age);
    }];
    
  • 3.4,削除データ
  • データの削除は、指定したデータにクエリーした後、コンテキストを介して直接オブジェクトを削除し、コンテキストを再保存するクエリーデータに基づいています.
    //6, 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Dogs"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age > 20"];
    request.predicate = predicate;
    
    NSError *error;
    NSArray *array = [_context executeFetchRequest:request error:&error];
    if (!error) {
        NSLog(@" ");
        // 
        [array enumerateObjectsUsingBlock:^(Dogs *dog, NSUInteger idx, BOOL * _Nonnull stop) {
            [_context deleteObject:dog];
            [_context save:nil];
        }];
    }
    
  • 3.5,更新データは削除データとほぼ一致しており,再付与後にdeleteObject:メソッドをupdatedObjectsメソッドに置き換えるだけでよいが,ここでは後述しないが,まだ分からない場合は,前の文書
  • .