iOS本地數(shù)據(jù)存儲

2019-04-13 11:00:14 正式開始寫簡書,為了記錄自己的學(xué)習(xí)經(jīng)歷,同時也分享自己的學(xué)習(xí)成果。當(dāng)然有不對的地方非常歡迎大家提出,這樣既能提高自己,也能防止誤導(dǎo)別人╮( ̄▽ ̄)╭

OK,進(jìn)入正題:

1.UserDefualt

最簡單的數(shù)據(jù)存儲方式了,直接上代碼

    //UserDefualt
    NSMutableArray *mutArr = [[NSMutableArray alloc] initWithObjects:@"1", @"2", nil];
    NSArray *arr = [NSArray array];
    //1.UserDefualt存儲數(shù)據(jù)
    [[NSUserDefaults standardUserDefaults] setObject:mutArr forKey:@"myData"];
    arr = [[NSUserDefaults standardUserDefaults] valueForKey:@"myData"];
    NSLog(@"arr = %@ \n", arr);
    
    [mutArr addObject:@"3"];
    [[NSUserDefaults standardUserDefaults] setObject:mutArr forKey:@"myData"];
    arr = [[NSUserDefaults standardUserDefaults] valueForKey:@"myData"];
    NSLog(@"arr = %@ \n", arr);

2.操作plist文件

對plist文件操作:需要獲取文件存儲路徑后創(chuàng)建.plist文件,之后用系統(tǒng)提供的NSFileManager對文件進(jìn)行操作,文件可以存在系統(tǒng)沙盒目錄下的Document或者Cache文件,這里選擇Document。

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"testLocalStorageData.plist"];
    NSLog(@"path = %@ \n", path);
    NSFileManager *fm = [NSFileManager defaultManager];
    [fm createFileAtPath:path contents:nil attributes:nil];
    //寫入
    NSDictionary *dic = @{@"value1":@"key1", @"value2":@"key2"};
    [dic writeToFile:path atomically:YES];
    //讀出
    NSDictionary *dicc = [NSDictionary dictionaryWithContentsOfFile:path];
    NSLog(@"dicc = %@ \n", dicc);

3.解歸檔

解歸檔能夠存儲對象數(shù)據(jù),需要實現(xiàn)<NSCoding>或者<NSSecureCoding>協(xié)議,后者有一定加密措施。
.h文件

@interface TestClass : NSObject <NSSecureCoding> //解歸檔遵守NSCoding協(xié)議

.m文件

#pragma mark -NSSecureCoding方法實現(xiàn)
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
    [aCoder encodeObject:self.test1 forKey:@"test1"];
    [aCoder encodeObject:self.test2 forKey:@"test2"];
    [aCoder encodeObject:self.test3 forKey:@"test3"];
    
}

- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
    if (self == [super init]) {
        self.test1 = [aDecoder decodeObjectForKey:@"test1"];
        self.test2 = [aDecoder decodeObjectForKey:@"test2"];
        self.test3 = [aDecoder decodeObjectForKey:@"test3"];
    }
    return self;
}
//加密協(xié)議需要實現(xiàn)下面的方法
+ (BOOL)supportsSecureCoding {
    return YES;
}

使用:

    TestClass *myclass = [TestClass new];
    myclass.test1 = @"123";
    myclass.test2 = @"456";
    myclass.test3 = @"789";
    NSLog(@"myclass = %@", myclass.test1);
    NSString *archPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
    NSString *archFilePath = [archPath stringByAppendingPathComponent:@"archData.data"];
    NSLog(@"----------%@", NSStringFromClass(myclass.class));
    NSError *error;
    //iOS12.0棄用
    //[NSKeyedArchiver archiveRootObject:myclass toFile:archFilePath];
    //歸檔
    NSData *archData = [NSKeyedArchiver archivedDataWithRootObject:myclass requiringSecureCoding:YES error:&error];
    NSLog(@"archData = %@", archData);
    if (error) {
        NSLog(@"archError : %@", error);
    }else{
        [archData writeToFile:archFilePath atomically:YES];
    }
    //解檔
    NSData *unarch = [[NSData alloc] initWithContentsOfFile:archFilePath];
    TestClass *content = [NSKeyedUnarchiver unarchivedObjectOfClass:NSClassFromString(@"TestClass") fromData:unarch error:&error];
    if (error){
        NSLog(@"unarchError->%@", error);
    }else{
        NSLog(@"content = %@", content.test1);
    }

4.CoreData

用來存儲數(shù)據(jù)形態(tài)更復(fù)雜的數(shù)據(jù),首先創(chuàng)建.xcdatamodeld文件,具體步驟:NewFile->DataModel->名字->創(chuàng)建。
CoreData.png

封裝CoreData方法為JCCoreDataManager

#import "JCCoreDataManager.h"

#define JC_CHECK_NSSTRING(str) ((str == nil) || ([str isEqualToString: @""]) || (str == NULL) || ([str isKindOfClass:[NSNull class]]))

@interface JCCoreDataManager(){
    NSString *path;
    NSString *dbFolderPath;
    
    NSError *error;
}

/**
 數(shù)據(jù)模型
 */
@property (nonatomic, strong) NSManagedObjectModel *objectModel;

/**
 管理數(shù)據(jù)的對象
 */
@property (nonatomic, strong) NSManagedObjectContext *objectContext;

/**
 持久化數(shù)據(jù)
 */
@property (nonatomic, strong) NSPersistentStoreCoordinator *coordinator;

@end

@implementation JCCoreDataManager

static JCCoreDataManager *manager = nil;

#pragma mark - 單例
+ (instancetype)sharedInstanceManager{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[JCCoreDataManager alloc] init];
    });
    return manager;
}


- (instancetype)init
{
    self = [super init];
    if (self) {
        //文件路徑
        path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
        dbFolderPath = [path stringByAppendingPathComponent:@"CoreData"];
        
        NSError *error;
        //創(chuàng)建托管對象模型
        NSURL *url = [[NSBundle mainBundle] URLForResource:@"TestModel" withExtension:@"momd"];
        _objectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
        //創(chuàng)建持久化協(xié)調(diào)器
        _coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_objectModel];
        //創(chuàng)建本地數(shù)據(jù)庫文件
        [_coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self dbPath] options:nil error:&error];
        //創(chuàng)建托管對象上下文
        _objectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_objectContext setPersistentStoreCoordinator:_coordinator];
    }
    return self;
}

/**
 獲取數(shù)據(jù)庫路徑

 @return NSURL
 */
- (NSURL *)dbPath {
    NSError *error = nil;
    if (![self checkPathExist]) {
        [[NSFileManager defaultManager] createDirectoryAtPath:dbFolderPath withIntermediateDirectories:YES attributes:nil error:&error];
    }
    if (error){
        NSLog(@"創(chuàng)建CoreManager文件失敗,error---->%@ \n", error);
        return nil;
    }
    NSURL *dbUrl = [[NSURL fileURLWithPath:dbFolderPath] URLByAppendingPathComponent:@"myDB.sqlite"];
    return dbUrl;
    
}

-(BOOL) checkPathExist{
    return [[NSFileManager defaultManager] fileExistsAtPath:dbFolderPath];
}

#pragma mark - 刪除數(shù)據(jù)庫
+ (NSString *)deleteCoreData{
    NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    NSString *fileFolderPath = [documentPath stringByAppendingPathComponent:@"CoreData"];
    NSError *error;
    if ([[NSFileManager defaultManager] fileExistsAtPath:fileFolderPath]){
        [[NSFileManager defaultManager] removeItemAtPath:fileFolderPath error:&error];
    }else{
        return @"沒有數(shù)據(jù),請先創(chuàng)建";
    }
    if (error){
        return [NSString stringWithFormat:@"刪除失敗,error--->%@", error];
    }
    return @"刪除成功";
    
}

//=============數(shù)據(jù)庫操作===============//
#pragma mark -獲取數(shù)據(jù)模型
+ (NSManagedObject *)getManagedObjectWithEntityName:(NSString *)entityName{
    NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:[JCCoreDataManager sharedInstanceManager].objectContext];
    return managedObject;
}
#pragma mark -存儲數(shù)據(jù)
+ (NSString *)save{
    JCCoreDataManager *manager = [JCCoreDataManager sharedInstanceManager];
    if (![manager checkPathExist]) {
        //manager = [[JCCoreDataManager alloc] init];
        [manager.coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[manager dbPath] options:nil error:nil];
    }
    NSError *saveError = nil;
    if ([manager.objectContext save:&saveError]) {
        return @"存儲成功";
    }else{
        return [NSString stringWithFormat:@"存儲失敗,error->%@", saveError];
    };
}

#pragma mark -更新數(shù)據(jù)
+ (BOOL)updateManagedObject:(NSManagedObject *)managedObject{
    [[JCCoreDataManager sharedInstanceManager].objectContext refreshObject:managedObject mergeChanges:YES];
    return [JCCoreDataManager save];
}

#pragma mark -查找數(shù)據(jù)

+ (NSArray *)searchCoreDataWithEntityName:(NSString *)entityName andAttribute:(NSString *)attribute andSelectName:(NSString *)searchName sorting:(NSString *)sortAttribute isAsending:(BOOL)isAsending{
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:[JCCoreDataManager sharedInstanceManager].objectContext];
    //創(chuàng)建fetch請求
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    fetchRequest.entity = entity;
    //一次獲取全部數(shù)據(jù)
    [fetchRequest setFetchBatchSize:0];
    NSSortDescriptor *nameDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    NSSortDescriptor *ageDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
    NSSortDescriptor *bloodTypeDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"bloodType" ascending:YES];
    if (JC_CHECK_NSSTRING(sortAttribute) || ([sortAttribute isEqualToString:@"name"])) {
//        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:sortAttribute ascending:isAsending];
        fetchRequest.sortDescriptors = @[nameDescriptor, ageDescriptor, bloodTypeDescriptor];
    }else if ([sortAttribute isEqualToString:@"age"]){
        fetchRequest.sortDescriptors = @[ageDescriptor, nameDescriptor, bloodTypeDescriptor];
    }else{
        fetchRequest.sortDescriptors = @[bloodTypeDescriptor, nameDescriptor, ageDescriptor];
    }
    if (!JC_CHECK_NSSTRING(attribute) && !JC_CHECK_NSSTRING(searchName)) {
        //查找某個屬性的值包含某個字符串
        //%K 屬性的值     %@ 字符串     ==
        fetchRequest.predicate = [NSPredicate predicateWithFormat:@"%K CONTAINS[cd] %@", attribute, searchName];
    }
    NSFetchedResultsController *fetchController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[JCCoreDataManager sharedInstanceManager].objectContext sectionNameKeyPath:nil cacheName:nil];
    NSError *error;
    if ([fetchController performFetch:&error]){
        return [fetchController fetchedObjects];
    }else{
        NSLog(@"%@", error);
        return @[];
    }
    
}

#pragma mark -刪除數(shù)據(jù)
+ (NSString *)deleteWithEntityName:(NSString *)entityName andAttribute:(NSString *)attribute andSearchName:(NSString *)searchName{
    //沒有刪除條件
    if (JC_CHECK_NSSTRING(attribute) || JC_CHECK_NSSTRING(searchName)) {
        return @"沒有刪除條件或條件不完整";
    }
    //查找
    NSArray *arr = [JCCoreDataManager searchCoreDataWithEntityName:entityName andAttribute:attribute andSelectName:searchName sorting:attribute isAsending:YES];
    if (arr.count == 0)
        return @"沒有找到數(shù)據(jù)";
    if (arr.count>0) {
        //刪除
        for (NSManagedObject *object in arr) {
            [[JCCoreDataManager sharedInstanceManager].objectContext deleteObject:object];
        }
    }
    //存儲數(shù)據(jù)
    [JCCoreDataManager save];
    return @"刪除成功";
    
}

@end

數(shù)據(jù)處理和創(chuàng)建都只針對JCStudentModel,后面會補(bǔ)充相關(guān)數(shù)據(jù)的創(chuàng)建、關(guān)聯(lián)、查找、刪除。
創(chuàng)建數(shù)據(jù)(10個隨機(jī)數(shù)據(jù)為例)

    for (int i = 0; i<10; i++) {
        JCStudentModel *studentModel = (JCStudentModel *)[JCCoreDataManager getManagedObjectWithEntityName:NSStringFromClass([JCStudentModel class])];
        uint32_t r = arc4random_uniform(99)+1;
        studentModel.name = [NSString stringWithFormat:@"student%@", r<10?[NSString stringWithFormat:@"0%u", r]:[NSString stringWithFormat:@"%u", r]];
        studentModel.age = arc4random_uniform(8)+10;
        studentModel.bloodType = arc4random_uniform(101)>50?@"A":@"B";
       
    }
    NSString *ans = [JCCoreDataManager save];

其他都只要調(diào)用一句即可:

//刪除所有數(shù)據(jù)
[JCCoreDataManager deleteCoreData];
//條件查找
NSArray *a = [JCCoreDataManager searchCoreDataWithEntityName:NSStringFromClass([JCStudentModel class]) andAttribute:attribute  andSelectName:selectName sorting:sortAttribute isAsending:YES];
//條件刪除
[JCCoreDataManager deleteWithEntityName:NSStringFromClass([JCStudentModel class]) andAttribute:attribute andSearchName:_keyWordsTextField.text];

目前就這些,歡迎大家批評指出不足:)

需要源碼的請訪問:https://github.com/daobao777/testLocalStorage

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容