iOS本地数据存储

2019-04-13  本文已影响0人  daobao777

2019-04-13 11:00:14 正式开始写简书,为了记录自己的学习经历,同时也分享自己的学习成果。当然有不对的地方非常欢迎大家提出,这样既能提高自己,也能防止误导别人╮( ̄▽ ̄)╭

OK,进入正题:

1.UserDefualt

最简单的数据存储方式了,直接上代码

    //UserDefualt
    NSMutableArray *mutArr = [[NSMutableArray alloc] initWithObjects:@"1", @"2", nil];
    NSArray *arr = [NSArray array];
    //1.UserDefualt存储数据
    [[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文件操作:需要获取文件存储路径后创建.plist文件,之后用系统提供的NSFileManager对文件进行操作,文件可以存在系统沙盒目录下的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.解归档

解归档能够存储对象数据,需要实现<NSCoding>或者<NSSecureCoding>协议,后者有一定加密措施。
.h文件

@interface TestClass : NSObject <NSSecureCoding> //解归档遵守NSCoding协议

.m文件

#pragma mark -NSSecureCoding方法实现
- (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;
}
//加密协议需要实现下面的方法
+ (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

用来存储数据形态更复杂的数据,首先创建.xcdatamodeld文件,具体步骤:NewFile->DataModel->名字->创建。 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;
}

/**
 数据模型
 */
@property (nonatomic, strong) NSManagedObjectModel *objectModel;

/**
 管理数据的对象
 */
@property (nonatomic, strong) NSManagedObjectContext *objectContext;

/**
 持久化数据
 */
@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;
        //创建托管对象模型
        NSURL *url = [[NSBundle mainBundle] URLForResource:@"TestModel" withExtension:@"momd"];
        _objectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
        //创建持久化协调器
        _coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_objectModel];
        //创建本地数据库文件
        [_coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self dbPath] options:nil error:&error];
        //创建托管对象上下文
        _objectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_objectContext setPersistentStoreCoordinator:_coordinator];
    }
    return self;
}

/**
 获取数据库路径

 @return NSURL
 */
- (NSURL *)dbPath {
    NSError *error = nil;
    if (![self checkPathExist]) {
        [[NSFileManager defaultManager] createDirectoryAtPath:dbFolderPath withIntermediateDirectories:YES attributes:nil error:&error];
    }
    if (error){
        NSLog(@"创建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 - 删除数据库
+ (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 @"没有数据,请先创建";
    }
    if (error){
        return [NSString stringWithFormat:@"删除失败,error--->%@", error];
    }
    return @"删除成功";
    
}

//=============数据库操作===============//
#pragma mark -获取数据模型
+ (NSManagedObject *)getManagedObjectWithEntityName:(NSString *)entityName{
    NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:[JCCoreDataManager sharedInstanceManager].objectContext];
    return managedObject;
}
#pragma mark -存储数据
+ (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 -更新数据
+ (BOOL)updateManagedObject:(NSManagedObject *)managedObject{
    [[JCCoreDataManager sharedInstanceManager].objectContext refreshObject:managedObject mergeChanges:YES];
    return [JCCoreDataManager save];
}

#pragma mark -查找数据

+ (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];
    //创建fetch请求
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    fetchRequest.entity = entity;
    //一次获取全部数据
    [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 -删除数据
+ (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 @"没有找到数据";
    if (arr.count>0) {
        //删除
        for (NSManagedObject *object in arr) {
            [[JCCoreDataManager sharedInstanceManager].objectContext deleteObject:object];
        }
    }
    //存储数据
    [JCCoreDataManager save];
    return @"删除成功";
    
}

@end

数据处理和创建都只针对JCStudentModel,后面会补充相关数据的创建、关联、查找、删除。
创建数据(10个随机数据为例)

    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];

其他都只要调用一句即可:

//删除所有数据
[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

上一篇下一篇

猜你喜欢

热点阅读