2016-03-02 17:33:50 ccflying88 阅读数 231

一、plist存储
1.获取Documents的路径,有两种方式:
<1>

NSString *home = NSHomeDirectory();  // 获取应用程序沙盒目录
//  获取到根目录后,设置路径
NSString *path = [home stringByAppendingString:@"/Documents"];
NSString *path = [home stringByAppendingPathComponent:@"Documents"];

NSUserDomainMask 表示在在用户目录下搜索,YES代表用户目录的~(主目录),NSDocumentDirectory 表示查找Document文件夹;
<2>

NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

2.写入到文件中

NSArray *arr;
[arr writeToFile:path atomically:YES];
NSDictionary *dict;
[dict writeToFile:path atomically:YES];

plist只能存储系统自带的一些常规的类,也就是有writeToFile方法的对象才可以使用plist保存数据;(例如:字符串、字典、数据、NSNumber、NSData…)自定义对象不能保存到plist中;

二、Preferences
偏好设置是专门用来保存应用程序的配置信息的,一般情况不要在偏好设置中保存其它数据;利用系统的偏好设置来存储数据,默认存储在Preferences文件夹下面;偏好设置会将所有的数据保存到同一个文件中;
存取步骤:
1.获取NSUserDefaults对象

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

2.保存数据

[defaults setObject:@"ccflying" forKey:@"name"];
[defaults setInteger:24 forKey:@"age"];
此操作不会立即保存数据到文件中,会在将来的某一个时间点自动将数据保存到Preferences文件夹下面 。
[defaults synchronize]; //  使NSUserDefaults立即保存数据

3.使用NSUserDefaults读取数据

[defaults objectForKey:@"name"];

三、NSKeyedArchiver 归档(NSCoding)
如果想将一个自定义对象保存到文件中,该对象必须实现NSCoding协议;
NSCoding有两个重要的方法:
1.存储

-(void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.age forKey:@"age"];
}  
// 当将一个自定义对象保存到文件的时候就会调用该方法,在该方法中实现具体的数据存储;

2.读取

-(id)initWithCoder:(NSCoder *)aDecoder
{
    if(self = [super init]){
    }
    return self;
}
// 当从文件中读取一个对象的时候就会调用此方法,在该方法中实现具体的数据的读取;

3.使用NSKeyedArchiver / NSKeyedUnarchiver存取对象

[NSKeyedArchiver archiveRootObject:p toFile:path];  // 存取数据
[NSKeyedUnarchiver unarchiveObjectWithFile:path];  // 读取数据

iOS会把PreferencesDocuments中的文件备份到iTunes;
tmp文件夹下的东西随时可能会被删除掉,而caches则不会;

四、文件解压缩
1.解压

NSString filepath; 
NSString caches;
[NSZipArchive unzipFileAtPath:filepath toDestination:caches]; 
// 该操作比较耗时

2.压缩

NSArray *pngs = [[NSBundle mainBundle] pathsForResourcesOfType:@"png" inDirectory:nil];  // 获取图片数组
NSString *path;  // .../pngs.zip
[NSZipArchive createZipFileAtPath:path withFilesAtPaths:pngs];
2016-05-24 23:16:24 qq_25737881 阅读数 81

一、ios应用数据存储的常用方式

  • XML属性列表(plist)归档
  • Preference(偏好设置)
  • NSKeyedArchiver归档(NSCoding)
  • SQLite3
  • Core Data

二、类型使用简述

1、XML属性列表(plist)归档
将数据以数组形式保存到plist列表中

2、Preference(偏好设置)
存储用户偏好设置

3、NSKeyedArchiver归档(NSCoding)
将数据保存到文件中

4、SQLite3
小型移动数据库处理,便于较大量数据增删改查

5、Core Data
苹果提供的数据库对象

2017-09-07 10:29:51 phyky 阅读数 4189

仅用于个人学习记录,代码不是最优写法,只是方便记录算法思想,会持续更新


链表

1、链表

  • 查找
  • 插入
  • 移除

2、栈(先进后出,尾部添加或删除元素)

  • push(入栈)
  • pop(出栈)
  • peek(获取顶部值)

3、队列(先进先出,尾部添加元素,头部删除元素)

  • enqueue(入队)
  • dequeue(出队)
  • peek(获取顶部值)

4、双链表(与链表区别在于,双向指针)

  • 查找
  • 插入
  • 移除

5、双端队列(与栈和队列的区别,首尾都能添加元素,首尾均能出列)

  • enqueue(入队)
  • dequeue(出队)
  • peek(获取顶部值)

排序算法

  • 冒泡排序
/*
 * 冒泡排序,相邻两个对比,前者比后者大,交换位置
 *
 */

-(void)bubbleSort{
    NSMutableArray *array = [NSMutableArray arrayWithArray:@[@3,@44,@38,@5,@47,@15,@36,@26,@27,@2,@46,@4,@19,@50,@49]];
    BOOL swapped = NO;
    do {
        swapped = NO;
        for (int i = 1; i < array.count; i++) {
            NSInteger num1 = [array[i-1] integerValue];
            NSInteger num2 = [array[i] integerValue];
            if (num1 >num2) {
                [array replaceObjectAtIndex:i-1 withObject:[NSNumber numberWithInteger:num2]];
                [array replaceObjectAtIndex:i withObject:[NSNumber numberWithInteger:num1]];
                swapped = YES;
            }
        }
    } while (swapped);
    NSLog(@"冒的排序:%@",array);
}
  • 选择排序
/*
 * 选择排序,标记最小值,循环比较,替换最小值
 *
 */

-(void)selectionSort{
    NSMutableArray *array = [NSMutableArray arrayWithArray:@[@3,@44,@38,@5,@47,@15,@36,@26,@27,@2,@46,@4,@19,@50,@49]];
    NSInteger repeatTimes = array.count -1;
    int sortBeginIndex = 0;//开始对比下标
    do {
        int miniNumIndex = sortBeginIndex;
        NSInteger miniNum = [array[sortBeginIndex] integerValue];
        for (int i = sortBeginIndex +1; i < array.count; i++) {
            NSInteger selectNum = [array[i] integerValue];
            if (selectNum < miniNum) {
                miniNum = selectNum;
                miniNumIndex = i;
            }
        }
        [array replaceObjectAtIndex:miniNumIndex withObject:array[sortBeginIndex]];
        [array replaceObjectAtIndex:sortBeginIndex withObject:[NSNumber numberWithInteger:miniNum]];
        sortBeginIndex ++;
        repeatTimes --;
    } while (repeatTimes > 0);
    NSLog(@"选择排序:%@",array);
}
  • 插入排序
/*
 * 插入排序,逐个元素拿出来,与其左边元素逐个对比,碰到比该元素小的元素,则插入在对比元素后
 *
 */

-(void)insertionSort{
    NSMutableArray *array = [NSMutableArray arrayWithArray:@[@3,@44,@38,@5,@47,@15,@36,@26,@27,@2,@46,@4,@19,@50,@49]];
    int sortBeginIndex = 1;//开始对比下标
    do {
        NSInteger sortBeginNum = [array[sortBeginIndex] integerValue];
        [array removeObjectAtIndex:sortBeginIndex];
        for (int i = sortBeginIndex -1; i >= 0; i--) {
            NSInteger compareNum = [array[i] integerValue];
            if (compareNum < sortBeginNum) {
                [array insertObject:[NSNumber numberWithInteger:sortBeginNum] atIndex:i+1];
                break;
            }else{
                if (i==0) {
                    [array insertObject:[NSNumber numberWithInteger:sortBeginNum] atIndex:0];
                }
            }
        }
        sortBeginIndex ++;
    } while (sortBeginIndex < array.count);
    NSLog(@"插入排序:%@",array);
}
2016-08-03 09:51:05 wanglei19940101 阅读数 465

iOS中关于数据存储需要注意的点,总结在下面:

关键数据

内容:用户创建的数据文件,无法在删除后自动重新创建

路径:主目录/Documents

管理:iOS系统即时遇到存储空间不足的情况下,也不会清除,同时会备份到iTunes或iCloud中

缓存数据

内容:可用于离线环境,可被重复下载重复生成,即使在离线时缺失,应用本身也可以正常运行

路径:主目录/Library/Caches

管理:在存储空间不足的情况下,会清空, 并且不会被自动备份到iTunes和iCloud中

临时数据

内容:应用运行时,为完成某个内部操作临时生成的文件

路径:主目录/tmp

管理:随时可能被iOS系统清除,且不会自动备份到iTunes和iCloud,尽量在文件不再使用时,应用自己清空,避免对用户设备空间的浪费

离线数据

内容:与缓存数据类似,可以被重新下载和重建,但是用户往往希望这些数据即使在存储紧张时也不会被系统自动删除

目录:主目录/Documents  或 主目录/Library/自定义的文件夹

管理:与关键数据类似,即使在存储空间不足的情况下也不会被清除,应用自己应该清除已经不再使用的文件,以免浪费用户设备空间 。需要设置”不备份到iCoud” ,否则会审核不过。

注意:

      如果你的App有离线数据下载功能,尤其需要关注这一点。因为离线数据一般占用存储空间比较大,可以被重新下载和重建,但是用户往往希望系统存储空间紧时也依然能够妥妥的存在着,不会被IOS系统自动清理掉。所以不能放在/Library/Caches 目录下(该目录在系统空间紧张时可能会被iOS系统清除)。 那就只能放在主目录/Documents  或 主目录/Library/自定义文件夹下,这样才不会被iOS系统自动清理掉。但是这些数据可能会很大,如果放在 主目录/Documents  或 主目录/Library/自定义的文件夹下,会被iCoud自动同步,那么用户需要为了同步消耗不少流量,苹果可能会因此拒绝你的应用上架。所以需要在程序中给自定义的目录设置“do not backup”属性。



2018-10-26 12:53:31 u013983033 阅读数 260

说到数据存储,我们不得不先了解下苹果的沙盒 、如何获取沙盒路径和沙盒目录下对应的文件:
一、沙盒(sandbox)

  • 每一个App都有一个存储空间。iOS系统为每个应用程序创建自己的目录,每个应用程序只能访问自己的目录,不能相互通信。
    沙盒主要包括下面几个文件:用模拟器运行 NSLog(@"%@",NSHomeDirectory()); 打印路径;
    进入该路径下回看到四个文件 Documents , Libraby , SystemData , tmp四个文件
    在这里插入图片描述

  • 各个文件的用途 :

  • 1、Documents
    获取路径

     NSString *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    

    保存持久化数据,会备份。一般用来存储需要持久化的数据。
    一般我们在项目中,我们会吧一些用户的登录信息进行存储,以及搜索历史记录等等一些关键数据。

    2、Library 下面有两个文件 Caches 和 Preferences
    Caches: iTunes不会同步此文件夹,适合存储体积大,不需要备份的非重要数据。
    获取路径

    NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
    

    Preferences: iTunes同步该应用时会同步此文件夹中的内容,通常保存应用的设置信息。NSUserDefaults存放

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    

    3、tmp
    iTunes不会同步此文件夹,系统可能在应用没运行时就删除该目录下的文件,所以此目录适合保存应用中的一些临时文件,用完就删除。
    获取路径

    NSString *path = NSTemporaryDirectory();
    

    在这里插入图片描述
    4、SystemData 这个是新加入的文件夹

二、 下面看下数据存储 包含: Preference 、文件存储、归档、数据库 、 CoreData
1、Preference(偏好设置): NSUserDefaults
可以存储 字典 数组 字符等系统自带的数据类型,自定义的对象无法存储,默认存放字 Library/Preferences 下 具体代码实现

    - (void)setDefault {
        //可以存储 字典 数组 字符等系统自带的数据类型,自定义的对象无法存储
        NSUserDefaults * def = [NSUserDefaults standardUserDefaults];
        [def setObject:@"aaaaaa" forKey:@"DEFAULT"];
        [def synchronize];
        NSLog(@"default ---- %@",[def objectForKey:@"DEFAULT"]);
    }
    - (void)delDefault {
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"DEFAULT"];
        NSLog(@"清空了default ---- %@",[[NSUserDefaults standardUserDefaults] objectForKey:@"DEFAULT"]);
    }

2 、文件存储
存储系统自带的数据类型,一般实际开发中存储字典、数组,自定义的模型无法进行存储
代码实习

   #define LvPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"lvData.plist"]
   #define LPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"lData.plist"]
   #define LhPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"lhData.plist"] 
- (void)createFile{
    //文件
    NSDictionary *dic = @{@"A":@"123"};
    NSArray * arr = @[@"Q",@"123"];
    NSString * string = @"aaaaaaaa";
    [dic writeToFile:LvPath atomically:YES];
    [arr writeToFile:LPath atomically:YES];
    [string writeToFile:LhPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    UIButton * fileBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    fileBtn.frame = CGRectMake(10, 180, 80, 80);
    [fileBtn setTitle:@"file" forState:UIControlStateNormal];
    fileBtn.backgroundColor = [UIColor redColor];
    [fileBtn addTarget:self action:@selector(setFile) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:fileBtn];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)setFile {
    NSArray * arr = [NSArray arrayWithContentsOfFile:LPath];
    NSDictionary * dic = [NSDictionary dictionaryWithContentsOfFile:LvPath];
    NSString * string = [NSString stringWithContentsOfFile:LhPath encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"file :arr--%@ dict---%@  string--%@",arr,dic,string);
}

3、归档(又名序列化)
归档是把对象转为字节码,以文件的形式存储到磁盘上,程序运行过程中或者再次重新打开程序的时候,可以通过解归档(返序列化)还原这些对象。
归档的对象是Foundation框架中的对象
归档和解归档其中任意对象都需要归档和解归档整个文件
归档后的文件是加密的,所以归档文件的扩展名可以随意取
在带键的归档中,每个归档都有一个key值,解归档时key值要与归档时key值匹配
代码实习 下面这个方法是卸载app ,再次装值也是还是之前的
LHKeyChain.m 文件

#import "LHKeyChain.h"

@implementation LHKeyChain
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (id)kSecClassGenericPassword,(id)kSecClass,
            service, (id)kSecAttrService,
            service, (id)kSecAttrAccount,
            (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
            nil];
}

+ (void)save:(NSString *)service data:(id)data {
    //Get search dictionary
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    //Delete old item before add new item
    SecItemDelete((CFDictionaryRef)keychainQuery);
    //Add new object to search dictionary(Attention:the data format)
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    //Add item to keychain with the search dictionary
    SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}

+ (id)load:(NSString *)service {
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    //Configure the search setting
    //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
        @try {
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
        } @catch (NSException *e) {
            NSLog(@"Unarchive of %@ failed: %@", service, e);
        } @finally {
        }
    }
    if (keyData)
        CFRelease(keyData);
    return ret;
}

+ (void)deleteKeyData:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
}

LHKeyChain.h

#import <Foundation/Foundation.h>

@interface LHKeyChain : NSObject
+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)deleteKeyData:(NSString *)service;
@end

调用 //归档

   - (void)setArchiver {
    NSString *IDFV = [LHKeyChain load:@"IDFV"];
    if ([IDFV isEqualToString:@""] || !IDFV) {
        IDFV = [UIDevice currentDevice].identifierForVendor.UUIDString;
        [LHKeyChain save:@"IDFV" data:IDFV];
    }
    NSLog(@"archiver---%@",[LHKeyChain load:@"IDFV"]);
    [LHKeyChain deleteKeyData:@"IDFV"];
    NSLog(@"archiver---%@",[LHKeyChain load:@"IDFV"]);
}

4 、数据库

SQLite数据库的几个特点:
1、基于C语言开发的轻型数据库
2、在iOS中需要使用C语言语法进行数据库操作、访问(无法使用ObjC直接访问,因为libqlite3框架基于C语言编写)
3、SQLite中采用的是动态数据类型,即使创建时定义了一种类型,在实际操作时也可以存储其他类型,但是推荐建库时使用合适的类型
4、建立连接后通常不需要关闭连接

SQLite 使用:

1、在iOS中使用SQLite3,首先要添加库文件libsqlite3.dylib和导入主头文件。如图
在这里插入图片描述
2、导入头文件,可以使用库中的函数

#import <sqlite3.h>

3、正好现在趁着数据持久化,讲下数据库增、删、改、查;有一个很好的第三方库 FMDB,这里不具体讲,详细使用可以点击了解详情 demo

1)创建并打开数据库
使用 sqlite3_open(<#const char *filename#>, <#sqlite3 **ppDb#>)函数的一些说明:把一个文件名称传递给他,它会自动检测这个文件是否存在,如果不存在的话,会自动创建相应的文件;

  • 参数说明它的第一个参数为文件的名称(需转换为C语言的),第二个参数是数据库的实例,sqlite3 *db;
  • 说明:sqlite3是一种类型,db是数据库的句柄,就是数据库的象征,如果要进行增删改查,就得操作db这个实例。
  • 返回值:它的返回值为int型的,根据函数的返回值可以知道,打开数据库文件是成功还是失败,如果返回值是SQLITE_OK则说明成功,否则为失败。

代码实现:

//数据库
- (void)createSqlite {
    //db是数据库的缩写
    sqlite3 * db;
    //这里面定义一个数据库存放路径,并获取到
    NSString * path = [NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) lastObject];
    NSString * dbPath = [path stringByAppendingString:@"demo.sqlite"];
    //因为sqlite是c语言 所以下面需要将OC字符串转换为c语言的字符串
    const char * cdbPath = dbPath.UTF8String;
    //下面打开数据库 (如果数据库存在的话,会直接打开,反之数据库不存在的话,会自动创建数据库文文件)
    int result = sqlite3_open(cdbPath, &db);
    if (result == SQLITE_OK) {
        NSLog(@"成功打开数据库");
    } else {
        NSLog(@"数据库打开失败");
    }
    //数据库 现在有了,接下来创建表
}

运行 查看结果 :
在这里插入图片描述
沙盒中已经存在 如图
在这里插入图片描述
数据库有了 ,下面就该创建表了
2)语句 sqlite3_exec(<#sqlite3 *#>, <#const char *sql#>, <#int (*callback)(void *, int, char **, char **)#>, <#void *#>, <#char **errmsg#>)

  • 参数:第一个参数为数据库的句柄(db),第二个参数为sql语句,第三个参数为回调参数,是一个指向函数的指针,如果把callback前面的*改成^则就是一个block代码段,第四个参数可以写NULL,第五个参数为错误信息,用以代码调试。

代码实现

 //db是数据库的缩写
 sqlite3 * db;
 //这里面定义一个数据库存放路径,并获取到
 NSString *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
 NSString * dbPath = [document stringByAppendingPathComponent:@"demo.sqlite"];
 //因为sqlite是c语言 所以下面需要将OC字符串转换为c语言的字符串
 const char * cdbPath = dbPath.UTF8String;
 //下面打开数据库 (如果数据库存在的话,会直接打开,反之数据库不存在的话,会自动创建数据库文文件)
 int result = sqlite3_open(cdbPath, &db);
 if (result == SQLITE_OK) {
      NSLog(@"成功打开数据库");
      //数据库 现在有了,接下来创建表
      const char * sql = "create table if not exists t_demo (id integer PRIMARY KEY AUTOINCREMENT,title text not null, content text not null)";
      char * errorMsg = NULL;
      result = sqlite3_exec(db, sql, NULL, NULL, &errorMsg);
      if (result == SQLITE_OK) {
            NSLog(@"表创建成功");
      } else {
            NSLog(@"表创建失败 %s",errorMsg);
      }
  } else {
      NSLog(@"数据库打开失败");
  }

运行结果
在这里插入图片描述
打开数据库 查看下成果:
在这里插入图片描述

现在表也有了 ,该对表进行操作了
3)插入数据
代码实现

  //1.拼接SQL语句
        NSString * title = [NSString stringWithFormat:@"title"];
        NSString * contet = [NSString stringWithFormat:@"content"];
        NSString *sql=[NSString stringWithFormat:@"INSERT INTO t_demo (title,content) VALUES ('%@','%@');",title,contet];
        //2.执行SQL语句
        char *errmsg=NULL;
        sqlite3_exec(db, sql.UTF8String, NULL, NULL, &errmsg);
        if (errmsg) {//如果有错误信息
            NSLog(@"插入数据失败--%s",errmsg);
        }else
        {
            NSLog(@"插入数据成功----%@",title);
        }

运行结果
在这里插入图片描述
查看数据库 如图
在这里插入图片描述
4) 下面看下修改数据

代码实现

//1.拼接SQL语句
    NSString * title = [NSString stringWithFormat:@"title--12"];
    NSString * contet = [NSString stringWithFormat:@"content--13"];
    NSString *sql=[NSString stringWithFormat:@"UPDATE t_demo set title =  '%@',content = '%@' where id = 2;",title,contet];
    //2.执行SQL语句
    char *errmsg=NULL;
    sqlite3_exec(db, sql.UTF8String, NULL, NULL, &errmsg);
    if (errmsg) {//如果有错误信息
        NSLog(@"更新数据失败--%s",errmsg);
    }else
    {
        NSLog(@"更新数据成功----%@",title);
    }

执行结果
在这里插入图片描述
在这里插入图片描述
5) 查询数据
语句:sqlite3_prepare_v2(<#sqlite3 *db#>, <#const char *zSql#>, <#int nByte#>, <#sqlite3_stmt **ppStmt#>, <#const char **pzTail#>)

  • 参数:第一个参数为数据库的句柄,第二个参数为sql语句,第三个参数为sql的长度(如果设置为-1,则代表系统会自动计算sql语句的长度),第四个参数用来取数据,第五个参数为尾部一般用不上可直接写NULL。

代码实现

 const char *sql="SELECT id,title,content FROM t_demo;";
    sqlite3_stmt *stmt=NULL;
    //进行查询前的准备工作
    if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL)==SQLITE_OK) {//SQL语句没有问题
        NSLog(@"查询语句没有问题");
        //每调用一次sqlite3_step函数,stmt就会指向下一条记录
        while (sqlite3_step(stmt)==SQLITE_ROW) {//找到一条记录
            //取出数据
            //(1)取出第0列字段的值(int类型的值)
            int ID = sqlite3_column_int(stmt, 0);
            //(2)取出第1列字段的值(text类型的值)
            const unsigned char * title = sqlite3_column_text(stmt, 1);
            //(3)取出第2列字段的值(int类型的值)
            const unsigned char * content = sqlite3_column_text(stmt, 2);
            //            NSLog(@"%d %s %d",ID,name,age);
            printf("%d %s %s\n",ID,title,content);
        }
    }else
    {
        NSLog(@"查询语句有问题");
    }

执行结果
在这里插入图片描述
6) 删除语句
代码实现

//1.拼接SQL语句
    NSString *sql=[NSString stringWithFormat:@"DELETE from  t_demo  where id = 2;"];
    //2.执行SQL语句
    char *errmsg=NULL;
    sqlite3_exec(db, sql.UTF8String, NULL, NULL, &errmsg);
    if (errmsg) {//如果有错误信息
        NSLog(@"删除数据失败--%s",errmsg);
    }else
    {
        NSLog(@"删除数据成功");
    }

执行结果 ,查看删除成功了
在这里插入图片描述
在这里插入图片描述

5、CoreData
Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也可以使用其他方式,比如:数据库文件,XML,二进制文件,内存等。CoreData 提供了 对象-关系映射(ORM) 功能,能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句;
本文 只讲简单的使用 下篇文字将学习CoreData具体的知识
代码实现 :
LHModel 类:
LHModel.h

#import <CoreData/CoreData.h>
@interface LHModel : NSManagedObject
@property (nonatomic, copy) NSString * title;
@property (nonatomic, copy) NSString * content;
@end

LJModel.m

#import "LHModel.h"
@implementation LHModel
@synthesize title;
@synthesize content;
@end

CoreDataViewController类 这个是我自己定义的类
CoreDataViewController.m

#import "CoreDataViewController.h"
#import <CoreData/CoreData.h>
#import "LHModel.h"
@interface CoreDataViewController ()
/**
 * 上下文  容器
 * 存放的是 所有从数据库中取出的转换成OC对象
 */
@property (strong, nonatomic) NSManagedObjectContext * managedObjectContext;

/* 读取解析 .momd文件中的内容 */
@property (strong, nonatomic) NSManagedObjectModel * managedObjectModel;

/* 连接的类,处理数据库数据和OC数据底层的相互转换 */
@property (strong, nonatomic) NSPersistentStoreCoordinator * persistentStoreCoordinator;
@end

@implementation CoreDataViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    NSLog(@"%@",self.managedObjectContext);
    
    
    //插入一条数据 (往LHModel表中插入一条数据)
    //NSEntityDescription 实体类
    //EntityForName 实体名称(表名)
    LHModel * model = [NSEntityDescription insertNewObjectForEntityForName:@"LHModel1" inManagedObjectContext:self.managedObjectContext];
    //赋值
    model.title = @"缓存1";
    model.content = @"缓存1内容";
    //同步操作  把context中的数据同步到数据库中
    [self saveContext];
    
    
    // 查询数据
    // 创建查询请求
    NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"LHModel1"];
    // Context 执行请求(执行查询操作) 数组中存放的是oc类的对象(People类的对象)
    NSArray * array = [self.managedObjectContext executeFetchRequest:request error:nil];
    for (LHModel *lhModel in array)
    {
        NSLog(@"%@",lhModel.title);
    }
    
    
    //查询特定条件数据
    NSFetchRequest * request1 = [NSFetchRequest fetchRequestWithEntityName:@"LHModel1"];
    //使用谓词指定查询的判定条件
    NSString * title = @"缓存1";
//    NSString *predStr = [NSString stringWithFormat:@"%@ AND (%@ CONTAINS \"%@\")", kPredicateStr_MovieItem_MoviesInCatalog, titleForSearch, title];
    
    NSPredicate * predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"SELF.title == '%@'",title]];
    //关联判定条件
    [request1 setPredicate:predicate];
    //执行查询操作
    NSArray * array2 = [self.managedObjectContext executeFetchRequest:request1 error:nil];
    for (LHModel * lhModel in array2)
    {
        NSLog(@"%@",lhModel.title);
    }
    
    //更改数据
    //获取出要修改的数据
    LHModel * lhModel = [array lastObject];
    //修改属性
    lhModel.title = @"缓存2";
    lhModel.content  = @"缓存2内容";
    //同步数据
    [self saveContext];
    
    
    //删除数据
    LHModel * lhModel1 = [array lastObject];
    [self.managedObjectContext deleteObject:lhModel1];
    //同步数据
    [self saveContext];
}

//managedObjectModel 属性的getter方法
- (NSManagedObjectModel *)managedObjectModel
{
    
    if (_managedObjectModel != nil) return _managedObjectModel;
    //.xcdatamodeld文件 编译之后变成.momd文件  (.mom文件)
    NSURL * modelURL = [[NSBundle mainBundle] URLForResource:@"MemoryData" withExtension:@"momd"];
    
    //把文件的内容读取到managedObjectModel中
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

//Coordinator 调度者负责数据库的操作 创建数据库 打开数据 增删改查数据
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) return _persistentStoreCoordinator;
    // 设置数据库存放的路径
    NSURL * storeURL = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:@"MemoryData.sqlite"];

    //根据model创建了persistentStoreCoordinator
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    
    
    
    NSError * error = nil;
    
    //如果没有得到数据库
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
    {
        NSLog(@"错误信息: %@, %@", error, [error userInfo]);
    }
    
    return _persistentStoreCoordinator;
}

//容器类 存放OC的对象
-(NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil)  return _managedObjectContext;
    
    NSPersistentStoreCoordinator * coordinator = [self persistentStoreCoordinator];
    if (!coordinator)
    {
        return nil;
    }
    
   /* 创建context对象 NSManagedObjectContext 实例提供一个线程。我们需要将这个 init 方法替换成 -initWithConcurrency: 方法。这个方法配置了 NSManagedObjectContext 实例化所在的线程。
    这就意味着我们要确定在哪个线程上实例化我们的 NSManagedObjectContext ,主线程,还是另外创建一个后台线程。我们可以选择的参数有:

    NSPrivateQueueConcurrencyType
    NSMainQueueConcurrencyType
    在这里,我把它配置成在主线程上进行实例化(一般选择主线程就可以)*/
    
  
    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
    //让context和coordinator关联   context可以对数据进行增删改查功能
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    
    return _managedObjectContext;
}

#pragma mark - Core Data Saving support

-(void)saveContext
{
    NSManagedObjectContext * managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil)
    {
        NSError * error = nil;
        // hasChanges 判断数据是否更改
        // sava 同步数据库中的数据
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
        {
            NSLog(@"错误信息: %@, %@", error, [error userInfo]);
        }
    }
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

运行结果 :

在这里插入图片描述
在这里插入图片描述

希望大家一起学习: 附有demo
csdn demo下载地址
https://download.csdn.net/download/u013983033/10745909

github demo 下载地址
https://github.com/lvhome/DataMemory

iOS 网络请求,数据解析

博文 来自: ccflying88

ios 数据库 (FMDB使用)

博文 来自: u013983033

iOS-数据存储

博文 来自: Setoge

IOS 数据解析

阅读数 439

IOS数据存储方式汇总

博文 来自: kyl282889543
没有更多推荐了,返回首页