沙河主要子目录:
/AppName.app:存放应用程序自身
/Documents/:这是文档目录。有关应用的所有数据文件应该写入到这个目录下,这个目录用于存储用户数据或者其他应该定期备份的信息。
/Library/:默认设置,下面有一些规范定义的的子目录,当然也可以自定义子目录,用于存放应用的文件,但是不宜存放用户数据文件,和document一样会被itunes同步,但不包括caches子目录
/Library/Preferences,这里存放程序规范要求的首选项文件,通过NSUserDefaults来获取和设置首选项。
/Library/Caches,保存应用的持久化数据,用于应用升级或者应用关闭后的数据保存,不会被itunes同步,所以为了减少同步的时间,可以考虑将一些比较大的文件而又不需要备份的文件放到这个目录下
/tmp/,保存应用数据,但不需要持久化的,在应用关闭后,该目录下的数据将删除,也可能系统在程序不运行的时候做清除
//打开是模拟器的路径
模拟器的app是systemData。
1、这是沙盒的入口文件(可直接打印)
NSString *homeDirectory = NSHomeDirectory();
NSLog(@“path:%@”, homeDirectory);
2、获取document目录
//第一种拼接办法
NSString *documentPath = [NSHomeDirectory() stringByAppendingString:@"document"];
//第二种函数办法(因为此函数返回的是数组)
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObject];
3、获取Cache目录
//第一种拼接办法
NSString *NSCachesDirectory = [NSHomeDirectory() stringByAppendingString:@"Cache"];
//第二种函数办法(因为此函数返回的是数组)
NSString *NSCachesDirectorys = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)firstObject];
4、获取Library目录
//第一种拼接办法
NSString *libraryPath = [NSHomeDirectory() stringByAppendingString:@"library"];
//第二种函数办法(因为此函数返回的是数组)
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)firstObject];
5、获取Tmp目录(也可以直接访问的存储空间)
NSString *tmpDir = NSTemporaryDirectory();
NSLog(@"%@", tmpDir);
//平时经常用document。
//其实info.plist和storyboard的文件都是可以解析成xml的,可以查看
一,解析info.plist文件(plist存储)
NSString *plistPath = [[NSBundle mainBundle]pathForResource:@“Info” ofType:@“plist”];
//拿到对应的plist字典
NSDictionary *plistDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
//可以对字典做相应的操作(读数据)
NSArray *allKey = [plistDictionary allKeys];
//也可以写数据(写到对应的沙盒里)
NSString *docStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES).firstObject stringByAppendingPathExtension:@"newFile"];
[plistPath writeToFile:docStr atomically:YES];
//其实为沙盒存储,其中为判断文件是否已存在方法,
//尽量不用数字路经中,
[NSFileManager defaultManager] fileExistsAtPath:fullPath]
二,NSUserdefault存储
开发的两个方法
存数据
[[NSUserDefaults standardUserDefaults] setObject:@“111” forKey:@“nameFiled”];
读数据
[[NSUserDefaults standardUserDefaults] objectForKey:@“nameFiled”];
还有一种是当新版本时,显示某界面的操作,是拿到本次的版本号,存到偏好设置里面,当下次启动的时候,查看版本号是否和之前一致,判断是否显示
//需要在application里设置拿到plist的CFBundleShortVersionString查看当前版本。在从NSUserDefaults里拿到本地版本,这样来判断是否为第一次打开该版本。
//需要在程序结束后把本地版本存起来。
NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults;
NSString *currentVersion = [NSBundle mainBundle].infoDictionary[@"CFBundleShortVersionString"];
NSString *localVersion = [userDefaults valueForKey:@"localVersion"];
!以上为沙盒存储,但是只能存储简单的数据,但是不能存储自定义模型数据。
三,NSKeyedArchiver,NSKeyedUnarchiver归档
//归档是序列化的过程,反归档是反序列化的过程,
1,苹果自带数据归档和反归档
self.data = [NSKeyedArchiver archivedDataWithRootObject:@[@"11",@"22"] requiringSecureCoding:YES error:nil];
//反归档
NSArray *dataArray = [NSKeyedUnarchiver unarchivedObjectOfClass:NSArray.class fromData:self.data error:nil];
2,自定义对象数据
//自定义对象的归档和反归档只要对象换一下就可以。但是对于自己写的model需要操作写数据。
要支持的协议
同时实现三个方法
• (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
[aCoder encodeObject:self.nameField forKey:@“name”];
[aCoder encodeInteger:self.age forKey:@“age”];
}• (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
if(self = [super init])
{
self.nameField = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
• (BOOL)supportsSecureCoding
{
return YES;
}
https://www.jianshu.com/p/3463b905d3dc 是归档详解
四,SQLite存储
//头文件引入#import “sqlite3.h”
//内嵌式(嵌入到一些小系统里面)占用资源也很低,支持window/linux/unix等等主流pc端操作,
支持的五种类型
1,NULL:表示该值为NULL值。
2,INTEGER:整型值。
3,REAL:浮点值。
4,TEXT:文本字符串,存储使用的编码方式为UTF-8,UTF-16等。
5,BLOB:二进制大对象是人意类型的数据。
SQLite常见函数
splite3_open
sqlite3_close
sqlite3_exec
sqlite3_prepare_v2
sqlite3_step
sqlite3_column_text
想要在工程中使用,必须要先导入该工程
在general下有一个Linked Frameworks and Libraries,点击+,引入libsqlite3.tbd。之后项目就会出现Frameworks的文件夹。
//以下为声明的一些方法。(用于实现增删改查)
• (void)createDB:(NSString *)dbName;
• (void)createTab:(NSString *)tabName;
• (void)insertMessage:(LHBMessage *)message;
• (void)deleteMessage:(NSString *)name;
• (void)updateMessage:(LHBMessage *)message;
• (NSArray<LHBMessage >)queryMessage;
• (NSArray<LHBMessage >)queryMessageByName:(NSString *)name;
• (void)dropTable:(NSString *)table;
//一下为各方法的实现
//数据库打开之后就要随时关闭,否则会浪费资源
- (void)createDB:(NSString *)dbName
{
// 1,查找沙盒
NSString *str = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES).firstObject;
NSLog(@"%@",str);
// 2,拼接数据库
NSString *strDocument = [str stringByAppendingPathComponent:dbName];
// 3,常用数据库(UTF8String是oc转c语言)
int result = sqlite3_open([strDocument UTF8String],&_sqlite);
if(result == SQLITE_OK){
NSLog(@"数据库创建成功");
}else{
NSLog(@"数据库创建失败");
}
}
- (void)createTab:(NSString *)tabName
{
//创建table。
NSString *sql = [NSString stringWithFormat:@"create table %@(id integer primary key autoincrement, name text,phone text,address text)",tabName];
NSLog(@"%@",sql);
char *error;
//c语言,数据库执行函数,两个null代表不需要回调,最后一个参数代表错误。
int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, &error);
if(result == SQLITE_OK){
NSLog(@"table创建成功");
}
else{
NSLog(@"table创建失败%s",error);
}
//sqlite3_close(_sqlite);
}
- (void)insertMessage:(LHBMessage *)message
{
NSString *sql = [NSString stringWithFormat:@"insert into test(name,phone,address) values ('%@','%@','%@')",message.name,message.phone,message.address];
int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, NULL);
if(result == SQLITE_OK){
NSLog(@"插入成功!");
}
else{
NSLog(@"插入失败!");
}
}
//一般很少进行数据库删除操作,要使用一定要进行一个弹窗提示,或者执行删除操作把该属性设为值,这样就可以达到查询时找不到该数据的效果
- (void)deleteMessage:(NSString *)name
{
NSString *sql = [NSString stringWithFormat:@"delete from test where name = '%@'",name];
int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, NULL);
if(result == SQLITE_OK){
NSLog(@"删除成功!");
}
else{
NSLog(@"删除失败!");
}
}
- (void)updateMessage:(LHBMessage *)message
{
NSString *sql = [NSString stringWithFormat:@"update test set phone = '%@' where name = '%@'",message.phone,message.name];
int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, NULL);
if(result == SQLITE_OK){
NSLog(@"更新成功!");
}
else{
NSLog(@"更新失败!");
}
}
- (NSArray<LHBMessage *> *)queryMessage
{
NSString *sql = [NSString stringWithFormat:@"select * from test"];
//sql语句的内部结构
sqlite3_stmt *stmt;
NSMutableArray *message = [[NSMutableArray alloc]init];
int result = sqlite3_prepare_v2(_sqlite, [sql UTF8String], -1, &stmt, NULL);
if(result == SQLITE_OK){
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char *nameStr =(const char *)sqlite3_column_text(stmt, 1);
const char *phoneStr =(const char *)sqlite3_column_text(stmt, 2);
const char *addressStr =(const char *)sqlite3_column_text(stmt, 3);
LHBMessage *lMessage = [[LHBMessage alloc]initWithObject:[NSString stringWithUTF8String:nameStr] withPhone:[NSString stringWithUTF8String:phoneStr] withAddress:[NSString stringWithUTF8String:addressStr]];
[message addObject:lMessage];
}
return message;
}
else{
NSLog(@"查询失败");
}
return nil;
}
- (void)dropTable:(NSString *)table
{
NSString *sql = [NSString stringWithFormat:@"drop table %@",table];
char *error;
int result = sqlite3_exec(_sqlite, [sql UTF8String], NULL, NULL, &error);
if(result == SQLITE_OK){
NSLog(@"删除表成功!");
}
else{
NSLog(@"删除表失败!%s",error);
}
}
//为判断是否table表已存在。
-(BOOL)checkName:(NSString *)name{
char *err;
NSString *sql = [NSString stringWithFormat:@"SELECT COUNT(*) FROM sqlite_master where type='table' and name='%@';",name];
const char *sql_stmt = [sql UTF8String];
if(sqlite3_exec(db, sql_stmt, NULL, NULL, &err) == 1){
return YES;
}else{
return NO;
}
}
!其中model想要输出对象,要实现其descripe函数,相当于java的tostring。
四,FMDB存储
sqlite3的封装,是一个第三方框架,因为sqlite3是对语言的封装,不太方便,所以FMDB就是完全对语言进行了oc的封装。
pod FMDB 此为第三方库
//头文件引入#import “fmdb/FMDB.h”
//声明fmdb的变量
@property (nonatomic,retain) FMDatabase *db;
//在tools工具类中相应完成打开数据库,创建table等操作。
//数据库打开之后就要随时关闭,否则会浪费资源
- (void)createDB
{
// 1,查找沙盒
NSString *str = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES).firstObject;
// 2,拼接数据库
NSString *strDocument = [str stringByAppendingPathComponent:@"Message.db"];
// 3,常用数据库
self.db = [FMDatabase databaseWithPath:strDocument];
BOOL isSuccess = [self.db open];
if(isSuccess){
NSLog(@"打开成功!");
}else{
NSLog(@"打开失败!");
}
}
//跟sqlite3不同的是,这里面要要把变量改成?。在executeUpdate的后面做相应的改变。
- (void)createTab
{
[self createDB];
//创建table。
NSString *sql = [NSString stringWithFormat:@"create table message(id integer primary key autoincrement, name text,phone text,address text)"];
BOOL isSuccess = [self.db executeUpdate:sql];
if(isSuccess){
NSLog(@"table创建成功");
}
else{
NSLog(@"table创建失败");
}
[self.db close];
}
//如果有基础数据就直接用@{}转变为对象。
- (void)insertMessage:(LHBMessage *)message
{
[self createDB];
NSString *sql = [NSString stringWithFormat:@"insert into message(name,phone,address) values (?,?,?)"];
BOOL isSuccess = [self.db executeUpdate:sql,message.name,message.phone,message.address];
if(isSuccess){
NSLog(@"table插入成功");
}
else{
NSLog(@"table插入失败");
}
[self.db close];
}
//做相应的数据库查询操作,用到函数excuteQuery
- (NSArray<LHBMessage *> *)queryMessageByName:(NSString *)name
{
[self createDB];
NSString *sql = [NSString stringWithFormat:@"select * from message where name = ?"];
//sql语句的内部结构
NSMutableArray *message = [[NSMutableArray alloc]init];
//先拿到结果集
FMResultSet *set = [self.db executeQuery:sql,name];
while ([set next]) {
NSString *nameStr = [set stringForColumnIndex:1];
NSString *phoneStr = [set stringForColumnIndex:2];
NSString *addressStr = [set stringForColumnIndex:3];
LHBMessage *lMessage = [[LHBMessage alloc]initWithObject:nameStr withPhone:phoneStr withAddress:addressStr];
[message addObject:lMessage];
}
[self.db close];
return message;
}