内存管理、数据存储
BAD_ACCESS在什么情况下出现
访问了野指针,比如访问已经释放对象的成员变量或者发消息、死循环等。
内存问题检查
内存检查:
1.Analyze静态分析 (command + shift + b),主要分析逻辑错误(访问空指针或未初始化的变量等)和内存管理错误(如内存泄漏)
2.使用Instruments工具的Leaks工具(product->profile ->leaks 打开工具主窗口)
3.观察Xcode的实时监测内存占用情况
4.第三方工具,如MLeaksFinder(查找未释放的类(在pop或dismiss的时候会调用自定义的willDealloc方法,如果2秒后未释放,就打印可能出现内存泄露的信息))
一般易造成泄漏的点:
1.循环引用,Block强引用,NSTimer释放不当
2.CoreFoundation或C语言的方式手动申请的内存,忘记释放
Instruments的常用工具
1). Time Profiler: 性能分析
2). Leaks:检查内存,看是否有内存泄露。
3). Zombies:检查是否访问了僵尸对象,但是这个工具只能从上往下检查,不智能。
4). Allocations:用来检查内存,写算法的那批人也用这个来检查。
iOS数据持久化方法
plist, NSUserDefault, NSKeyArchiver, SQLite, CoreData
iOS的沙盒目录结构
1). Application:存放程序源文件,上架前经过数字签名,上架后不可修改。
2). Documents:常用目录,iCloud备份目录,存放数据。(这里不能存缓存文件,否则上架不被通过)
3). Library:
Caches:存放体积大又不需要备份的数据。(常用的缓存路径)
Preference:设置目录,iCloud会备份设置信息。
4). tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能。
SQLite基本语法:
创表:create table if not exist
增:insert;删:delete;改:update;查:query
SQLite FMDB基本语句
// 创建数据库实例对象
self.db = [FMDatabase databaseWithPath:filename];
// 创表
BOOL result = [self.db executeUpdate:@"create table if not exists t_Record (type int, title text, startTime date, endTime date, state text, Id long);"];
// 增
res = [self.db executeUpdate:@"insert into t_Record (type, title, startTime, endTime, state, Id) values (?, ?, ?, ?, ?, ?);",
@(record.type), record.title, record.startTime, record.endTime, record.state, @(record.Id)];
// 改
res = [self.db executeUpdate:@"update t_Record set type = ? title = ?, startTime = ?, endTime = ?, state = ? where Id = ?;",
@(record.type), record.title, record.startTime, record.endTime, record.state, @(record.Id)];
// 查询
// FMResultSet *rs = [self.db executeQuery:@"select * from t_Schedule where creatTimeNum > ?;", @0];
FMResultSet *rs = [self.db executeQuery:@"select * from t_Record"];
// 删除
BOOL res = [_db executeUpdate:@"delete from t_Record where Id = ?", @(record.Id)];
//事务
__block BOOL success = YES;
[self.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
@try {
success = [db executeUpdate:@"update t_student set age = ? where name = ?;", @20, @"jack"];
}
@catch (NSException *exception) {
*rollback = YES;
success = NO;
}
@finally {
*rollback = !success;
}
}];
或: [db beginTransaction]; [db rollback]; [db commit];
数据库事务的四个特性
⑴ 原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
⑵ 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
⑶ 隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
关于事务的隔离性数据库提供了多种隔离级别。
⑷ 持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。
fmdb如何使用异步存储
把fmdb封装成一个单例,在单例力创建一个全局的信号量,操作数据库时都通过信号量控制,包括增删改查
CoreData基本使用
创建:
1.创建表Company.xcdatamodel,添加实体
2.创建实体关联类,继承自NSManagedObject
3.创建NSManagedObjectContext,包含NSPersistentStoreCoordinator
4.增:Employee *emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:_context];
[_context save:&error];
- FectchRequest 抓取请求对象 , 谓语查找NSPredicate, 排序NSSortDescriptor
NSArray *emps = [_context executeFetchRequest:request error:&error];
另外可以通过创建工程勾选coreData,APPDelegate会自动生成NSPersistentContainer类,包含ViewContext对象
优点:可视化操作(表、关联对象),不用写SQL语句;
缺点:笨重,增加、删除字段时要进行数据库升级,否则会造成闪退
注:
NSPersistentStoreCoordinator是持久化存储协调者,主要用于协调
托管对象上下文和持久化存储区之间的关系。
NSManagedObjectContext使用协调者的托管对象模型将数据保存到数
据库,或查询数据。