一. 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.引用计数式内存管理分为以下四种
- 自己生成的对象,自己持有
- 非自己生成的对象,自己持有
- 自己持有的对象不再需要时释放
- 非自己持有的对象无法释放
网友评论