当前位置:首页 » 存储配置 » ios对象存储

ios对象存储

发布时间: 2023-09-05 10:09:36

① iOS数据存储(一)介绍

iOS本地化存储的数据保存在沙盒中。
(1) Documents :iTunes会备份该目录。一般用来存储需要持久化的数据。
(2) Library/Caches :缓存,iTunes不会备份该目录。内存不足时会被清除,应用没有运行时,可能会被清除。一般存储体积大、不需要备份的非重要数据。
(3) Library/Preference :iTunes同会备份该目录,可以用来存储一些偏好设置。
(4) tmp : iTunes不会备份这个目录,用来保存临时数据,应用退出时会清除该目录下的数据。

获取沙盒文件:

其中:

  可以把字典或数组直接写入到文件中。另外, NSString 、 NSData 、 NSNumber 等类型,也可以使用 writeToFile:atomically: 方法直接将对象写入文件中,只是 Type 为空。

   NSUserDefaults是轻量级存储,一般使用它来进行一些设置的记录,比如用户ID,开关是否打开等设置,通过键值对的方式记录设置,所以这个有时候也被称为偏好设置。
  NSUserDefaults可以存储的数据类型包括: NSData 、 NSString 、 NSNumber 、 NSDate 、 NSArray 、 NSDictionary 。如果要存储其他类型,则需要转换为前面的类型,才能用NSUserDefaults存储。

也可以写成宏定义

② 第五篇:IOS类探究(成员变量值放在哪里,成员变量信息放在哪里)

我们简单写个demo,在我们定义的类HPWPerson里放了name,age属性,还有_hobby成员变量

首先我们考虑两个问题,类方法是放在哪里?成员变量是放在哪里?带着这两个问题我们进行深入的探究下。

我们通过上篇结尾的分析其实知道,实例方法,成员属性,协议等都是存放在class_rw_t这个结构体里,如下面源码所示,

我们继续在class_rw_t结构体源码里找下,发现有class_ro_t这个结构体,这个结构体是干什么的呢?

我们通过打印得到如下:

@property (nonatomic ,) NSString *name;这个会生成下划线的成员变量_name,
@property (nonatomic ,assign) int age;这个会生成下划线的成员变量_age,
发现我们再打印class_ro_t里发现有上图所示的成员变量,所以其中“_hobby”,“_age”,"_name"这些是存在class_ro_t这个结构里的。

通过上面我们发现,成员变量的值是放在对象里,成名变量名字以及一些大小信息放在类里面,这个是为什么呢?其实类里面的结构体它就好比山坦一个模板,通过这个模板就可以生成各个成员变量信息,但是成员变量的值是不同的所以成员变量的值要存放在实例对象里,成员变量名及大小信息放在类里面就可以。

接着我们再继续探究下,在class_rw_t这个结构体里有class_ro_t这个结构体,那这两个结构体有什么关系呢?

1.class_ro_t是在编译的时候生成的(只读),是一个纯净的空间,不能被修改的

我们知道苹果的runtime可以动态的修改属性和方法,但是ro里又不支持修改的,那它是如何实现的呢?
我们先看下WWDC里的一个视频讲解:
WWDC讲解ro,rw链接

通过上面的视频我罩唯举们知道,ro在编译的时候生成,在内存不够的时候就会进行移除,当要使用的时候就会重新从磁盘里去加载。在objc源码里我们发现有个叫class_rw_ext_t的结构体,简称为rwe。class_rw_ext_t这个也不是每个类里都生成的,因为生成class_rw_ext_t是有条件的:或者有分类,或者runtime API修改的时候会生成这个rwe结构体。runtime是无法修改成员变量的,rwe在对ro里进行拷贝出的也是其中一部分,一般ro里也就10%的内容需要修改。接着我们看rwe源码如下,也验证了我们这点:如果有rwe就直接返回里面的methods,没有就返回ro里的baseMethods。

属性存放在rw里源码:如果有rwe就直接返回里面的properties,没有就返回ro里的baseProperties。

协议存放在rw里源码:如果有rwe就直接返回里面的protocols,没有就返回ro里的baseProtocols。

设计元类只是单独为了存放我们的类方法吗?

其实其目的是为了复用消息机制。在OC中调⽤⽅法,其实是在给某个对象发送某条消息。
消息的发送在编译的时候编译器就会把⽅法转换为objc_msgSend这个函数。
id objc_msgSend(id self, SEL op, ...) 这个函数有俩个隐式的参数:消息的接收者,消息的⽅法
名。通过这俩个参数就能去找到对应⽅法的实现。
objc_msgSend函数就会通过第⼀个参数消息的接收者的isa指针,找到对应的类,如果我们是通过
实例对象调⽤⽅法,那么这个isa指针就会找到实例对象的类对象,如果是类对象,就会找到类对
象的元类对象,然后再通过SEL⽅法名找到对应的imp,然后就能找到⽅法对应的实现。
那如果没有元类的话,那这个objc_msgSend⽅法还得多加俩个参数,⼀个参数⽤来判断这个⽅法
到底是类⽅法还是实例⽅法。⼀个参数⽤来判断消息的接受者到底是类对象还是实例对象。
消息的发送,越快越好。那如果没物碧有元类,在objc_msgSend内部就会有有很多的判断,就会影响
消息的发送效率。
所以元类的出现就解决了这个问题,让各类各司其职,实例对象就⼲存储属性值的事,类对象存储
实例⽅法列表,元类对象存储类⽅法列表,符合设计原则中的单⼀职责,⽽且忽略了对对象类型的
判断和⽅法类型的判断可以⼤⼤的提升消息发送的效率,并且在不同种类的⽅法⾛的都是同⼀套流
程,在之后的维护上也⼤⼤节约了成本。
所以这个元类的出现,最⼤的好处就是能够复⽤消息传递这套机制。不管你是什么类型的⽅法,都
是同⼀套流程。

接着我们如何证明我们上面所说的呢?下面我们来看下在源码里设置断点调试:

首先我们打开objc的源码,

我们一直按上面去打印,最后会打印一个classMethod这个类方法,在我们设置HPWPerson这个类里也有这个方法,如下,所以证明了类方法是存放在元类里面的。

接着我们看些runtime的api方法的实现:

上面这些我们是用runtime的api把成员变量,实例方法,类方法等打印出来。
通过上面总结:
1)ro里存放成员变量,实例方法,属性,协议,类对象
2)类方法存放在元类里面

③ ios 中数组中存储自定义的对象,怎么将这个数组保存成本地文件

第一步:要将数组中的对象需要遵循 NSCoding 协议,实现协议中的两个方法。
第二步:通过 NSKeyedArchive 进行快速归档,它会自动写到文件中,读取可以使用 NSKeyedUnarchiver 来解压
代码例子在网上都能找到。

④ ios开发中数据持久化有哪几种,分别什么时间使用

1、plist文件(属性列表),通常用于储存用户设置,也可以用于存储捆绑的信息;
2、preference(偏好设置),常用于保存少量数据;
3、NSKeyedArchiver(归档),将内存中的对象实例保存成binary到磁盘并且可以逆向这个过程用来保存用户操作状态等;
4、sqlite 3,使用数据库进行存储;
5、CoreData,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。

⑤ iOS存储技术-Keychain

钥匙串这个技术大家每天都在用,它相当于一个容器,里面有已加密的和未加密的用户信息,它是怎么实现安全储存Mac、App、服务器和网站的帐户,开发过程中又该怎么使用这个技术呢。通过一个例子来介绍一下:

用户要登录你的APP,这个时候用户在文本框输入了他的用户信息和密码,那么你该如何存储这个信息?自然我们会有一个类似用户的结构来存储用户信息

这个结构里有一个String类型的用户名称和一个String类型的密码变量, 张三输入了它自己的用户名“zhangsan”和密码“******”来登陆,那么我们就会有一个生成用户的过程

那么接下来你希望存储到Keychain中,Keychain有哪些方法呢?第一步自然是添加

函数有三个参数,但是每个似乎都不认识,所以我们先简单看一下这三个参数要做什么

第一个参数是个字典,那自然是由许多key-value构成,首先它要包含一个这个数据的类型,数据类型使用kSecClass来做key,kSecClass的定义:

可以看到kSecClass是一个CFString类型的全局变量,它其中可用的值由Item Class Keys and Values列出。根据数据类型的不同有不同的值,例如密码、认证,对于密码它的值定义为:

也是一个CFString类型的变量, class对应的值会决定数据是否被加密,当选择这个password的时候数据就会被加密。那么我们字典中的第一个key-value对就有了:

那么这个字典还需要包含什么呢? 账号:也就是这个数据是谁的数据,这个属性由kSecAttrAccount这个Key来定义,同样它也是一个CFString类型的Key,它的值是你自定义的一个CFString类型的值。当然这个属性并不是必须的,于是字典中的第二个key-value对也有了

⚠️注意

字典中除了用户名还需要用户的数据,数据使用kSecValueData这个Key来定义,同样是CFString类型的Key,但是用户的数据可能多种多样,所以它的值类型是CFData。那么就需要把用户的信息加工一下

这样就得到了字典中第三个key-value对:

既然是钥匙串,那就不能随时随地访问,需要访问控制权限,所谓访问控制就是你希望当iPhone解锁的时候,或者是验证了用户的指纹之后才能继续进行的过程。权限由kSecAttrAccessControl这个Key来表示,它所对应的值是一个SecAccessControl的实例,而SecAccessControl又是什么?

它就是一个包含Keychain对象怎么被使用的信息的一个不透明类型,来看看它的实例化

它通过(CFAllocatorRef allocator, CFTypeRef protection, SecAccessControlCreateFlags flags, CFErrorRef _Nullable *error)函数来创建
函数有四个参数:
1.第一个参数是用来初始化SecAccessControlRef对象的. 我们可以传 NULL 或者kCFAllocatorDefault
2.第二个参数是控制设备什么情况下可以访问这个Keychain信息, 它的值可以是添加Keychain函数的第一个参数字典中的一个其它key(kSecAttrAccessible)对应的值,例如可以控制当设备解锁的时候使用的值:: CFString。其它可使用的还有(只有这台设备且设置了密码)、(只有这个设备第一次解锁后)。
3.第三个参数是一组额外的访问控制:用来控制用户级别的访问权限,如果设备没有密码总是处于unlocked的状态,你可能希望进一步限制KeyChain访问。例如在获取银行账户的认证时候,需要在获取认证信息之前验证是不是授权用户在操作,这使得KeyChain可以根据用户的输入来管理对Keychain的访问,可以选择devicePasscode来限制需要用户需要输入密码或者是选择userPresence来让系统根据当前状态选择一种验证方式或者是多种方式的组合
第四个是失败原因的一个指针,这里暂时传一个nil值
所以我们可以通过来获得一个访问控制的参数

⚠️注意

现在我们可以回到之前创建函数的第一个参数字典的分析了,我们得到了
SecAccessControl的实例,所以字典的第四个key-value对也有了:

现在字典中有了数据的类型、哪个用户的数据、用户要存储的数据、什么条件可以访问这个数据。看起来不缺少什么了。我们的一个字典参数就处理好了:

函数会通过第二个参数来返回新添加的Keychain,具体的类型是根据第一个参数中指定的返回类型决定的(例如可以通过kSecReturnData这个可以指定返回类型为CFData) 当然,通常我们可以忽略这个返回的数据,所以可以传一个nil值
函数还有一个返回值,从声明上看是一个OSStatus类型的值,相应的定义在Security Framework Result Codes中,常见的值有:

我们通常需要将返回值和已知的返回值相比较来判断是否操作成功了,也就是我们通常可以使用如下的语句来处理添加操作

至此,添加操作就完成了。

查询主要使用SecItemCopyMatching(CFDictionaryRef query, CFTypeRef _Nullable *result)函数,函数会返回一个或者多个item,或者是指定的item属性的,默认情况下只会返回匹配的第一个结果。

函数的第一个参数就是和添加Keychain函数的参数一样的结构,通常有Keychain的class也就是由kSecClass为Key的一个key-value对。
属性:属性就是Keychain结果需要符合的条件,例如想查找哪个用户的数据,查询参数还可以带控制返回的key,因为添加方法和查询方法都会返回结果的数据和属性到提供的参数指针里,所以可以指定返回的key来控制指针对应的返回数据的格式,也就是通常的密码查询应该包含kSecReturnData为Key的key-value对。
例如可以使用kSecReturnPersistentRef这个Key来获得一个CFData的引用,然后可以把它存储在磁盘或在进程间传递,可以在这之后调用另一个SecItemCopyMatching函数将持久化引用转为常规引用,函数参数里需要将持久化的引用的数组作为kSecMatchItemList的值传入。如果使用kSecReturnData来控制返回data本身,搜索会返回一个代表实际数据的CFData,这个就是典型的密码Keychain的使用方式。同时,Keychain服务会在返回给你之前对数据进行解密
搜索参数:这个参数可以包含一些结果的数量条件,控制string属性是否大小写敏感等。
所以,希望查询上面的用户信息的时候查询字典参数会如下所示

函数的第二个参数是一个CFTypeRef类型的接收函数返回的指针,我们需要先定义一个这样的指针:

同样我们需要判断函数返回值是否成功:

因为查询字典参数里携带了kSecReturnData,所以这个指针指向的数据类型是一个CFData类型的参数,我们需要获取对应的值

这样 str就是我们之前存储在KeyChain中的用户信息了
至此,Keychain的添加和删除都已经具备了,基本的用户需求就解决了。

除了基础的使用之外,我们还可以

这些,下次再说吧

⑥ iOS开发怎么获取本地数据和把数据存储到本地

一般获取本地数据是从plist文件中读取JSON数据。
读取数据:
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"city" ofType:@"plist"];

NSArrary *cityArray = [[NSArray alloc]initWithContentsOfFile:plistPath];
这里的cityArray根据你存在plist中的数据类型来确定,如果plist中是字典类型,那么你这里需要使用NSDictionary去存储你从plist中获取到的数据。

至于本地存储数据的话根据你项目的具体功能来设计,一般的小型数据如用户昵称、手机号等使用NSUserDefault即可,但是如果是大量数据如账单类app中的账单数据那么此时需要考虑使用sqlite3去存储数据,至于密码之类就需要使用NSKeydArchiver去存储。

⑦ iOS开发之数据存储以及删除

iOS本地数据保存有多种方式,归纳如下:

本章不仅是学习多种数据存储方式,也可学习到其他知识点,下面就让我们详细来看:

具体方培梁核法为:
第一步:获得文件即将保存的路径,并生成在该路径下的文件:

第二步:往文件中写入/读取:
方法一:

方法配掘二:

方法三:

2.NSUserDefaults:是一个单例对象,在整个应用程序的生命周期中都只有一个实例。用渣旅来保存应用程序设置和属性、用户保存的数据。存储在沙盒的Library/Preference中,NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。写入和读取都比较简单,如下:
写入:

NSString *str = [userDefault objectForKey:@"gang"];

@interface Person : NSObject <NSCoding>//遵守NSCoding协议
@property (nonatomic,strong) NSString *name;
@property (nonatomic,assign) NSInteger age;
@end

解档操作:
同样调用NSCoder子类NSKeyedArchiver的方法unarchiveRootObject:toFile: 即可
[NSKeyedUnarchiver unarchiveObjectWithFile:path];

NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archiver encodeObject:person forKey:@"person"];
[archiver encodeObject:bir forKey:@"bir"];
// 存档完毕(一定要调用这个方法)
[archiver finishEncoding];
[data writeToFile:path atomically:YES];

NSData *undata = [NSData dataWithContentsOfFile:path];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
[unarchiver decodeObjectForKey:@"person"];
[unarchiver decodeObjectForKey:@"bir"];
// 恢复完毕
[unarchiver finishDecoding];

热点内容
长安欧尚科赛哪个配置值得购买 发布:2025-01-28 03:19:35 浏览:115
c全排列算法 发布:2025-01-28 03:18:16 浏览:753
梵蒂冈顶级时装ftp 发布:2025-01-28 03:03:36 浏览:694
手游脚本有前途吗 发布:2025-01-28 02:46:55 浏览:378
抓包编程 发布:2025-01-28 02:42:41 浏览:929
安卓平板上怎么设置热点 发布:2025-01-28 02:36:33 浏览:717
如何在手机上压缩图片 发布:2025-01-28 02:34:09 浏览:989
服务器ip挂上公网 发布:2025-01-28 02:31:15 浏览:978
吃鸡配置需要什么条件 发布:2025-01-28 02:26:15 浏览:9
58怎么上传简历 发布:2025-01-28 02:17:45 浏览:38