一、基础概念
常量:不会被程序修改的量(用
const
修饰)
变量:存放的是数据本身。
指针变量:存储的是数据的地址(指针本身也有地址)。
const
修饰 常量
static
修饰 静态变量
extern
修饰 全局变量
变量名、内存地址、变量值?
变量名:实际上是一个符号地址
,在对程序编译连接时由系统给每一个变量名分配一个内存地址
。在程序中从变量中取值,实际上是通过变量名找到相应的内存地址,从其存储单元中读取数据。
芯片手册的符号表大概是这么写:
地址 | 名称 | 值 |
---|---|---|
0x00 | CHIP_ID | 0x03 |
0x01 | CHIP_VERSION | 0xA2 |
0x02 | CHIP_SIZE | 0xFF |
0x03 | …… | …… |
“ 程序 ” 经过编译连接后形成的二进制映像文件,这文件包含:栈,堆,数据段 和 代码段组成。
1、栈区
:由编译器自动分配释放,存放函数的参数值,局部变量等值。
2、堆区
:允许程序在运行时动态地申请某个大小的内存。一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。
3、数据段_Data
:1.只读数据段;2.已经初始化读写数据段;3.未初始化数据段即BBS。(包括:常量、常变量(const 变量)、静态变量、全局变量等)
4、代码段_Text
:存放函数体的二进制代码,编译后会生成CPU机器指令。
- 静态存储区域:代码段、数据段(变量、常量)
- 动态存储区域:堆区、栈区
1、静态存储方式
程序未运行,编译阶段根据需要分配固定的存储空间。
2、动态存储方式
是指在程序运行期间根据需要进行动态的分配存储空间的方式。
动态存储变量是在程序执行过程中,使用它时才分配存储单元, 使用完毕立即释放。 (例如函数的调用,参数的使用)
变量分为:全局变量、局部变量。
(局部变量 = 内部变量 = 自动变量 = 临时变量)
1、全局变量
:Global variables 也称为外部变量。作用域是从变量的定义处开始
,到本程序文件
的结尾。(用extern
修饰)
在此作用域内,全局变量可为各个函数所引用。编译时将外部变量分配在静态存储区
。
- 使用全局变量会占用更多的内存(因为其生命期长)。
- 程序运行时速度更快一些(因为内存不需要再分配)
- 当全局变量与局部变量
重名
的时候,起作用的是局部变量,全局变量被屏蔽掉。 - 还可以用
extern
在函数外对全局变量声明,使全局变量的作用域从声明处到文件的结束。
#全局常量:不会被修改。
extern NSString * const LMJName = @"iOS开发者公会;
2、局部变量
:局部作用域的变量。存放在栈区,在栈区里面其实又可以分成好几个区域,他们叫做栈桢,一个栈桢就是一个函数,需要调用该函数的时候就如入栈,函数return的时候就会弹出栈,所以他们的生命周期是从函数的开始直到函数结束。
3、静态变量
:静态区域分配的变量。(用 static修饰)
static
修饰的已经初始化的变量,是一个私有的全局变量。修饰的变量值,可以改变。
-
static 全局变量:只初使化一次,作用域被限制在该变量的源文件内有效,防止在其他文件单元中被引。
-
static 局部变量:只被初始化一次,下一次依据上一次结果值。
-
static 常量: static const var
const
修饰的变量是不可变的,如果需要定义一个时间间隔的静态常量,就可以使用const修饰。
# 1、如果试图修改 TimeDuration 编译器则会报错。
static const NSTimeInterval TimeDuration = 0.5;
# 2、如果我们定义一个字符串类型的静态常量就要注意了,这两种写法是一样的,而且是可以修改的。
static NSString const * name = @"iOS开发者公会";
static const NSString * name = @"iOS开发者公会";
这两种写法cons修饰的是* name,*是指针指向符,也就是说此时指向内存 "地址" 是不可变的,而内存保存的 "内容" 是可变的。
所以我们应该这样写:()
static NSString * const name = @"iOS开发者公会";
# 所以:当我们定义一个对象类型常量的时候,要将const修饰符放到*指针指向符后面。
在OC中static修饰的变量是不能通过类名直接访问的,它只作用于它声明所在的.m
文件中。static修饰的变量必须放在@implementation
外面或方法中,它只在程序启动初始化一次。
常量区(特殊的常量存储区,属于静态存储区)
- 常量占用内存,只读状态,决不可修改
- 常量字符串就是放在这里的,程序结束后由系统释放
二、数据持久化
苹果提供了四种持久化方案供:
1、属性列表(plist)存储App信息、城市列表等。
2、数据归档(NSKeyedValueArchiver)
3、NSUserDefaults:用于存储用户设置、用户信息等。
4、coreData
5、沙盒/数据库(sqlite)

1、属性列表(plist):
轻量级存储方式,其存储格式有多种,最常规格式为XML格式。
在我们创建一个新的项目的时候,Xcode会自动生成一个info.plist
文件用来存储项目的部分系统设置。plist只能用数组(NSArray
)或者字典(NSDictionary
)进行读取,由于属性列表本身不加密,所以安全性几乎可以说为零。
2、数据归档(NSKeyedValueArchiver)
与属性列表相反,同样作为轻量级存储的持久化方案,数据归档是进行加密处理的,数据在经过归档处理会转换成二进制数据,所以安全性要远远高于属性列表。另外使用归档方式,我们可以将复杂的对象写入文件中,并且不管添加多少对象,将对象写入磁盘的方式都是一样的
使用NSKeyedArchiver对自定义的数据进行序列化,并且保存在沙盒目录下。使用这种归档的前提是让存储的数据模型遵守NSCoding
协议并且实现其两个协议方法。(当然,如果为了更加安全的存储,也可以遵守NSSecureCoding
协议,这是iOS6之后新增的特性)
NSKeyedArchiver
和NSKeyedUnarchiver
进行数据的归档和解档操作。把数据存储到沙盒文件里面去,就能将数据保存到本地磁盘里面。
存储的数据都是不可变的,想将可变数据存入需要先转为不可变才可以存储.
3、用户的偏好设置(NSUserDefaults)
NSUserDefaults
是定时把缓存中的数据写入磁盘的,而不是即时写入,为了防止在写完NSUserDefaults后程序退出导致的数据丢失,可以在写入数据后使用synchronize
立即将数据强制写入磁盘
。
synchronize:
作为多线程关键字, 是一种同步锁
。它可以修饰以下几种对象:
-
代码块
:被修饰的代码块称为同步语句块,其作用的范围是大括号{ }里的代码,作用的对象是调用这个代码块的对象; -
方法
:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; -
静态方法
:作用的范围是整个静态方法,作用的对象是这个类的所有对象;
-类
:作用的范围是synchronize后面括号里的部分,作用的对象是这个类的所有对象。
4、数据库(sqlite)
sqlite是一个轻量级、跨平台的小型数据库,其拥有可移植性高、有着和MySql几乎相同的数据库语句以及无需服务器即可使用的优点
:
1)可以存储大量的数据,存储和检索的速度非常快;
2)能对数据进行大量的聚合,这样比起使用对象来进行这些操作要快。
当然,它也具有明显的缺点
:
1)它没有提供数据库的创建方式;
2)它基于C语言框架设计,没有面向对象的API,所以使用起来比较麻烦;
3)复杂的数据模型的数据建表相对而言比较麻烦。
当然,我们也可以使用基于sqlite封装的开源数据库FMDB来减少使用sqlite的工作量。 唐巧的<YTKKeyValueStore> 是对 FMDB 的封装,使用功能起来更加方便。
4、coreData
coreData 是苹果官方iOS5之后推出的综合型数据库,其使用了ORM(Object Relational Mapping)
对象关系映射技术,将对象转换成数据,存储在本地数据库中。coreData为了提高效率,甚至将数据存储在不同的数据库中,且在使用的时候将本地数据放到内存中使得访问速度更快。我们可以选择coreData的数据存储方式,包括sqlite、xml
等格式。但也正是coreData 是完全面向对象的,其在执行效率上比不上原生的数据库。除此之外,coreData拥有数据验证、undo
等其他功能,在功能上是四种持久化方案最多的。
它们的区别如下:

未完待续。。。
参考文章:
1、动态存储区、静态存储区、堆和栈的区别
2、iOS数据库之FMDB、Realm、WCDB
3、iOS数据持久化:使用NSKeyedArchiver进行数据归档
网友评论