美文网首页
SQLite,NSUserDefaults,plist文件

SQLite,NSUserDefaults,plist文件

作者: 皮蛋豆腐酱油 | 来源:发表于2019-08-12 17:14 被阅读0次

一. SQLite数据库实际操作

1. 什么是SQLite

  • 嵌入式的关系型数据库
  • 轻量化
  • 存储大量数据
  • 支持语言多

2. 常用SQLite操作

  • 创建数据表
    CREATE TABLE CONTACTS (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    NAME TEXT,
    ADDRESS TEXT,
    PHONE TEXT
    );
    AUTOINCREMENT 是自动增加
    PRIMARY KEY 是主码
    INTEGER 数字类型
    TEXT 字符串类型

  • 向数据表添加数据
    INSERT INTO CONTACTS (NAME,ADDRESS,PHONE)
    VALUES("张三","南京路","18612345678");
    ID字段会自动增加,无需插入

  • 从数据表中删除数据
    DELETE FROM CONTACTS
    WHERE NAME = "张三";

  • 修改数据表中的数据
    UPDATE CONTACTS
    SET NAME = "王五"
    WHERE NAME = "张三";

  • 读取数据表
    SELECT *
    FROM CONTACTS;

3. SQLite实际操作


二. 在iOS端实现SQLite操作

添加libsqlite3.tbd


//
//  ViewController.m
//  SQLiteDemo

#import "ViewController.h"
#import <sqlite3.h>
@interface ViewController ()

- (IBAction)createTableAction:(id)sender;
- (IBAction)addRowAction:(id)sender;
- (IBAction)deleteRowAction:(id)sender;
- (IBAction)modifyRowAction:(id)sender;
- (IBAction)readRowsAction:(id)sender;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}


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

- (NSString *)sqliteFilePath {
    //获取cache目录
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    //拼接文件名
    NSString *databasePath = [cachePath stringByAppendingPathComponent:@"contacts.sqlite"];
    return databasePath;
}

//创建数据表
- (void)createSqliteTable {
    //获取数据库文件路径
    NSString *dbFilePath = [self sqliteFilePath];
    //将路径字符串转换成UTF-8
    char *dbPath = [dbFilePath UTF8String];
    //声明sqlite数据库结构体的指针
    sqlite3 *contactDB;
    //sqlite3_open将会打开数据库文件,如果文件不存在,它会创建该数据库文件
    if (sqlite3_open(dbPath, &contactDB) == SQLITE_OK) {
        NSLog(@"数据库打开/创建成功");
    } else {
        NSLog(@"数据库打开/创建失败");
    }
    
    //生成指令
    char sqlite_stmt[1000];
    snprintf(sqlite_stmt, 1000, "CREATE TABLE CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT,ADDRESS TEXT,PHONE TEXT)");
    
    //执行语句
    //第三个参数为NULL表示不使用回调
    if (sqlite3_exec(contactDB, sqlite_stmt, NULL, NULL, NULL) == SQLITE_OK) {
        NSLog(@"创建表成功");
    } else {
        NSLog(@"创建表失败");
    }
    
    //关闭数据库
    sqlite3_close(contactDB);
}

//增加数据
- (void)addRow {
    //获取数据库文件路径
    NSString *dbFilePath = [self sqliteFilePath];
    //将路径字符串转换成UTF-8
    char *dbPath = [dbFilePath UTF8String];
    //声明sqlite数据库结构体的指针
    sqlite3 *contactDB;
    //sqlite3_open将会打开数据库文件,如果文件不存在,它会创建该数据库文件
    if (sqlite3_open(dbPath, &contactDB) == SQLITE_OK) {
        NSLog(@"数据库打开/创建成功");
    } else {
        NSLog(@"数据库打开/创建失败");
    }
    
    //生成指令
    char sqlite_stmt[1000];
    //双引号使用转义字符\
    
    snprintf(sqlite_stmt, 1000, "INSERT INTO CONTACTS (NAME,ADDRESS,PHONE)VALUES(\"张三\",\"南京路\",\"18612345678\")");
    
    //执行语句
    //第三个参数为NULL表示不使用回调
    if (sqlite3_exec(contactDB, sqlite_stmt, NULL, NULL, NULL) == SQLITE_OK) {
        NSLog(@"插入数据成功");
    } else {
        NSLog(@"插入数据失败");
    }
    
    //关闭数据库
    sqlite3_close(contactDB);
}

//删除数据
- (void)deleteRow {
    //获取数据库文件路径
    NSString *dbFilePath = [self sqliteFilePath];
    //将路径字符串转换成UTF-8
    char *dbPath = [dbFilePath UTF8String];
    //声明sqlite数据库结构体的指针
    sqlite3 *contactDB;
    //sqlite3_open将会打开数据库文件,如果文件不存在,它会创建该数据库文件
    if (sqlite3_open(dbPath, &contactDB) == SQLITE_OK) {
        NSLog(@"数据库打开/创建成功");
    } else {
        NSLog(@"数据库打开/创建失败");
    }
    
    //生成指令
    char sqlite_stmt[1000];
    //双引号使用转义字符\
    
    snprintf(sqlite_stmt, 1000, "DELETE FROM CONTACTS WHERE NAME = \"张三\"");
    
    //执行语句
    //第三个参数为NULL表示不使用回调
    if (sqlite3_exec(contactDB, sqlite_stmt, NULL, NULL, NULL) == SQLITE_OK) {
        NSLog(@"删除数据成功");
    } else {
        NSLog(@"删除数据失败");
    }
    
    //关闭数据库
    sqlite3_close(contactDB);
}

//修改数据
- (void)modifyRow {
    //获取数据库文件路径
    NSString *dbFilePath = [self sqliteFilePath];
    //将路径字符串转换成UTF-8
    char *dbPath = [dbFilePath UTF8String];
    //声明sqlite数据库结构体的指针
    sqlite3 *contactDB;
    //sqlite3_open将会打开数据库文件,如果文件不存在,它会创建该数据库文件
    if (sqlite3_open(dbPath, &contactDB) == SQLITE_OK) {
        NSLog(@"数据库打开/创建成功");
    } else {
        NSLog(@"数据库打开/创建失败");
    }
    
    //生成指令
    char sqlite_stmt[1000];
    //双引号使用转义字符\
    
    snprintf(sqlite_stmt, 1000, "UPDATE CONTACTS SET NAME = \"李四\" WHERE NAME = \"张三\"");
    
    //执行语句
    //第三个参数为NULL表示不使用回调
    if (sqlite3_exec(contactDB, sqlite_stmt, NULL, NULL, NULL) == SQLITE_OK) {
        NSLog(@"修改数据成功");
    } else {
        NSLog(@"修改数据失败");
    }
    
    //关闭数据库
    sqlite3_close(contactDB);
}

//查询数据库
- (void)readRows {
    //获取数据库文件路径
    NSString *dbFilePath = [self sqliteFilePath];
    //将路径字符串转换成UTF-8
    char *dbPath = [dbFilePath UTF8String];
    //声明sqlite数据库结构体的指针
    sqlite3 *contactDB;
    //sqlite3_open将会打开数据库文件,如果文件不存在,它会创建该数据库文件
    if (sqlite3_open(dbPath, &contactDB) == SQLITE_OK) {
        NSLog(@"数据库打开/创建成功");
    } else {
        NSLog(@"数据库打开/创建失败");
    }
    
    //生成指令
    char sqlite_stmt[1000];
    snprintf(sqlite_stmt, 1000, "SELECT * FROM CONTACTS");
    //准备一个SQLite语句,用于执行,目的是优化执行时间 
    sqlite3_stmt *statement;
    //初始化statement实例,-1表示不指定长度
    sqlite3_prepare_v2(contactDB, sqlite_stmt, -1, &statement, NULL);
    
    //执行一条准备的语句,如果找到一行匹配的数据,则返回SQLITE_ROW
    while (sqlite3_step(statement) == SQLITE_ROW) {
        //获取到一行数据
        NSInteger index = sqlite3_column_int(statement, 0);
        NSString *name = [[NSString alloc]initWithUTF8String:(const char*)sqlite3_column_text(statement , 1)];
        NSString *address = [[NSString alloc]initWithUTF8String:(const char*)sqlite3_column_text(statement , 2)];
        NSString *phone = [[NSString alloc]initWithUTF8String:(const char*)sqlite3_column_text(statement , 3)];
        NSLog(@"%ld | %@ | %@ | %@",index,name,address,phone);
    }
    NSLog(@"数据库读取完毕");
    //在内存中,清理之前准备的语句
    sqlite3_finalize(statement);
    
    //关闭数据库
    sqlite3_close(contactDB);
}
- (IBAction)createTableAction:(id)sender {
    [self createSqliteTable];
}

- (IBAction)addRowAction:(id)sender {
    [self addRow];
}

- (IBAction)deleteRowAction:(id)sender {
    [self deleteRow];
}

- (IBAction)modifyRowAction:(id)sender {
    [self modifyRow];
}

- (IBAction)readRowsAction:(id)sender {
    [self readRows];
}
@end

一. 偏好存储使用场景

  • 用户存储偏好设置
  • 缓存信息
  • 轻量级数据存储
  • 不可用于存储大量数据
  • 不要滥用synchronize方法
  • 警惕数据被清空,因为NSUserDefaults是单例类,代码的任何地方都可以将它删除

二. 偏好存储工作原理

三. 偏好存储支持的数据类型

不可存储可变类型



不可存储可变类

四. 偏好存储的增加、读取、修改、删除

//
//  ViewController.m
//  UserDefaultDemo


#import "ViewController.h"

@interface ViewController ()
- (IBAction)addPreference:(id)sender;
- (IBAction)readPreference:(id)sender;
- (IBAction)modifyPreference:(id)sender;
- (IBAction)deletePreference:(id)sender;
- (IBAction)clearAllPreference:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}


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


- (IBAction)addPreference:(id)sender {
    //增加偏好设置
    //获取NSUserDefault类实例
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    //存储数字类型
    [userDefaults setBool:NO forKey:@"BoolKey"];
    [userDefaults setInteger:123 forKey:@"IntegerKey"];
    [userDefaults setFloat:0.123 forKey:@"FloatKey"];
    [userDefaults setDouble:0.123456 forKey:@"DoubleKey"];
    //存储字符串类型
    [userDefaults setObject:@"Hello" forKey:@"StringKey"];
    //存储NSData类型
    NSData *data = [@"hello Data" dataUsingEncoding:NSUTF8StringEncoding];
    [userDefaults setObject:data forKey:@"DataKey"];
    //存储数组类型
    NSArray *array = @[@"one",@"two",@"three"];
    [userDefaults setObject:array forKey:@"ArrayKey"];
    //存储字典类型
    NSDictionary *dict = @{@"key1":@"value1",@"key2":@"value2",@"key3":@"value3"};
    [userDefaults setObject:dict forKey:@"DictionaryKey"];
    
    [userDefaults synchronize];//将存储的偏好存储内容同步到ROM中
}

- (IBAction)readPreference:(id)sender {
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    //读取数字值
    BOOL readBool = [userDefaults boolForKey:@"BoolKey"];
    NSLog(@"Bool value is:%@",readBool?@"YES":@"NO");
    
    NSInteger readInteger = [userDefaults integerForKey:@"IntegerKey"];
    NSLog(@"Integer value is:%ld",readInteger);
    
    float readFloat = [userDefaults floatForKey:@"FloatKey"];
    NSLog(@"Float value is:%f",readFloat);
    
    double readDouble = [userDefaults doubleForKey:@"DoubleKey"];
    NSLog(@"Double value is:%lf",readDouble);
    
    //读取字符串值
    NSString* readString = [userDefaults objectForKey:@"StringKey"];
    NSLog(@"String value is:%@",readString);
    
    //读取NSData值
    NSData* readData = [userDefaults objectForKey:@"NSDataKey"];
    NSString* dataToString = [[NSString alloc]initWithData:readData encoding:NSUTF8StringEncoding];
    NSLog(@"NSData value is:%@",dataToString);
    //读取数组值
    NSArray* readArray = [userDefaults objectForKey:@"ArrayKey"];
    NSLog(@"Array value is:%@",readArray);
    //读取字典值
    NSDictionary* readDictionary = [userDefaults objectForKey:@"DictionaryKey"];
    NSLog(@"Dictionary value is:%@",readDictionary);
}

- (IBAction)modifyPreference:(id)sender {
    //修改偏好设置 修改和增加其实是一样的
    //获取NSUserDefault类实例
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    //更新数字类型
    [userDefaults setBool:YES forKey:@"BoolKey"];
    [userDefaults setInteger:456 forKey:@"IntegerKey"];
    [userDefaults setFloat:3.14 forKey:@"FloatKey"];
    [userDefaults setDouble:9.87654 forKey:@"DoubleKey"];
    //更新字符串类型
    [userDefaults setObject:@"World" forKey:@"StringKey"];
    //更新NSData类型
    NSData *data = [@"new Data" dataUsingEncoding:NSUTF8StringEncoding];
    [userDefaults setObject:data forKey:@"DataKey"];
    //更新数组类型
    NSArray *array = @[@"four",@"five",@"six"];
    [userDefaults setObject:array forKey:@"ArrayKey"];
    //更新字典类型
    NSDictionary *dict = @{@"key5":@"value5",@"key6":@"value6",@"key7":@"value7"};
    [userDefaults setObject:dict forKey:@"DictionaryKey"];
    
    [userDefaults synchronize];//将存储的偏好存储内容同步到ROM中
}

- (IBAction)deletePreference:(id)sender {
    //获取NSUserDefaults实例
    NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
    
    //存储数字值
    [userDefaults removeObjectForKey:@"BoolKey"];
    [userDefaults removeObjectForKey:@"IntegerKey"];
    [userDefaults removeObjectForKey:@"FloatKey"];
    [userDefaults removeObjectForKey:@"DoubleKey"];
    //存储字符串值
    [userDefaults removeObjectForKey:@"StringKey"];
    //存储NSData值
    [userDefaults removeObjectForKey:@"NSDataKey"];
    //存储数组值
    [userDefaults removeObjectForKey:@"ArrayKey"];
    //存储字典值
    [userDefaults removeObjectForKey:@"DictionaryKey"];
    
    //同步数据
    [userDefaults synchronize];
}

- (IBAction)clearAllPreference:(id)sender {
    //删除所有偏好存储
    //获得应用的域的字符串
    NSString *appDomainString = [[NSBundle mainBundle]bundleIdentifier];
    //清空偏好存储
    [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomainString];
}
@end

OC-plist文件写入与读取

在Objective-C开发中,和后续的iOS开发中,经常会碰到需要解析plist文件的。本章简单的来看一下plist文件如何写入与读取.

plist:Property List属性列表,Plist文件通常用于储存用户设置,也可以用于存储捆绑的信息,plist文件的根节点只有array和dictionary两种。

下面来看代码:

将数组对象和字典对象写入到plist文件中。

plist文件的写入:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        NSArray *array = [[NSArray alloc] initWithObjects:@"one",@"two",[NSNumber numberWithInt:123],[NSDate date], nil];
        //如果传入的目录中没有对应的app.plist文件,则会自动创建一个app.plist文件
        //plist文件的根节点(Root)只能是数组(Array)或是字典(Dictionary)
        //plist文件中存储的对象只能为7种类型的数据NSArray NSDictionary NSString NSData NSDate NSNumber Boolean
        BOOL flag = [array writeToFile:@"/Users/qianfeng/Desktop/lpj/app.plist" atomically:YES];
        if (flag) {
            NSLog(@"array 文件写入成功");
        }else{
            NSLog(@"array 文件写入失败");
        }
        
        NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"111",@"ont",@"222",@"two",[NSDate date],@"date",[NSNumber numberWithInteger:1111],@"integer",[NSArray arrayWithObjects:@"000",@"111",@"222", nil],@"array", nil];
        BOOL flag1 = [dict writeToFile:@"/Users/qianfeng/Desktop/lpj/ff/app.plist" atomically:YES];
        if (flag1) {
            NSLog(@"dictionary 文件写入成功");
        }else{
            NSLog(@"dictionary 文件写入失败");
        }
        
    }
    return 0;
}

plist文件的读取:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //将plist文件读取为字典对象
        NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:@"/Users/qianfeng/Desktop/day21-OC11_时间类/day21_OC11_plist读取/apple.plist"];
        if (dict) {
            NSLog(@"dict = %@",dict);
        }
        else{
            NSLog(@"dictionary 数据为空");
        }
     
        //将plist文件读取为数组对象
        NSArray *array = [NSArray arrayWithContentsOfFile:@"/Users/qianfeng/Desktop/day21-OC11_时间类/day21_OC11_plist读取/app.plist"];
        if (array) {
            NSLog(@"array = %@",array);
        }
        else{
            NSLog(@"array 数据为空");
        }
        
    }
    return 0;
}

ARC和MRC

1.自己生成并持有对象

用alloc/new/copy/mutableCopy方法生成的对象为自己生成,其他则为非自己生成。

2.非自己生成对象被自己持有

{
id obj = [NSMutableArray array];
/*[NSMutableArray array]生成的对象B(假如叫做B),但不被obj持有  
这时直接调用[obj release];是不行的,会导致程序崩溃*/
[obj retain];
//此时持有B
[obj release];
//释放B
}

3.引用计数式内存管理分为以下四种

  • 自己生成的对象,自己持有
  • 非自己生成的对象,自己持有
  • 自己持有的对象不再需要时释放
  • 非自己持有的对象无法释放

相关文章

网友评论

      本文标题:SQLite,NSUserDefaults,plist文件

      本文链接:https://www.haomeiwen.com/subject/ntrayqtx.html