黑马程序员技术交流社区

标题: 06Foundation框架(3): 数组的持久化,NSFileManger,结构体,集... [打印本页]

作者: bjwqcpy@126.com    时间: 2016-10-15 20:07
标题: 06Foundation框架(3): 数组的持久化,NSFileManger,结构体,集...

1. 数组的持久化.

    将数组中所有的元素的值存储到磁盘上的文件中.

    plist: 属性列表文件.

    - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;

    文件的路径,文件后缀名写plist

    属性列表文件的好处: 一目了然.

    从plist文件中还原数组.

    + (nullable NSArray<ObjectType> *)arrayWithContentsOfFile:(NSString *)path;



NSDictionay

1. 先回顾一下NSArray和NSMutbaleArray.

    是OC中的数组.

    NSMutableArray数组的缺点:

    NSMutableArray数组中的元素一旦删除.

    这个元素后面的元素的下标会发生变化 会往前顶.

    下标不靠谱. 要找到数组中特定的1个元素 不要使用下标去找,因为元素的下标可能会发生变化.

    需求: 希望有一种靠谱的方式来快速定位数组中的元素.

        

    每存储1个数据,都要求为这个数据取1个别名,

    要找存储在数组中的数据的时候,不是通过下标来找,而是通过别名来找.

    这样就算数组的元素的下标发生了变化. 不影响我们查找数据.因为我们不是通过下标来找数据 而是通过别名来找.

    这中存储数据的方式我们叫做 键值对 的存储方式.

    每存储1个数据(值) Value,都要为这个数据取1个别名(键).Key

    NSDictionay 和 NSMutableDictionary 就是以键值对的形式来存储数据的.

2. NSDictionary数组.

    1). 不可变字典数组.

    2). 特点:

        a. 首先是1个数组.

        b. 是以键值对的形式来存储数据的

        c. 存储的数据只能是OC对象.别名只能是遵守了NSCopying协议的OC对象. NSString就是遵守这个协议的.

        d. 存储的键值对是固定的.不能动态的新增和删除.

3. 创建NSDictionary字典数组.

    1). 这是1个类.要使用它的话,就必须要创建对象来使用.

         NSDictionary *dict1 = [NSDictionary new];

         NSDictionary *dict2 = [[NSDictionary alloc] init];

         NSDictionary *dict3 = [NSDictionary dictionary];

        这样的创建出来的字典数组,没有意义.这个时候这个字典数组的长度为0

        而这个字典数组无法新增和删除元素.所以没有意义.

    2). 常用的创建字典数组的方法

        + (instancetype)dictionaryWithObjectsAndKeys:(id)firstObject, ...

        NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"rose",@"name",@"18",@"age",@"178.5",@"height",nil];

        依次的将值、键写在参数.最后1个写nil

    3). 简要NSDictionary字典数组的方式.

        NSDictionary *dict = @{键1:值1,键2:值2,键3:值3 ......};

         NSDictionary *dict = @{

            @"name":@"rose",

            @"age":@"18",

            @"height":@"178.6"

         };

         

4. 如何取出存储在字典数组中的数据.

    1). 字典数组中的数据不能使用下标去取.只能使用Key取Key对应的值.

    2). 如何使用key取到这个key所对应的值.

        a. 使用中括弧,在中括弧中写上别名,就可以取到这个别名对应的数据.

           dict[别名];

        b. 调用字典对象的方法.

            

           - (nullable ObjectType)objectForKey:(KeyType)aKey;

        如果给定的Key不存在,取到的就是nil.

5.  取到字典数组中键值对的个数.

     @property (readonly) NSUInteger count;

6. 字典数组中的键是不能重复的. 因为键是用来区分字典数组中值的唯一标识.

     如果键重复???????

7. NSDictionary字典数组的遍历.

    1). 因为 NSDictionary字典数组中的取值是依靠键来取值的.无法通过下标来取值.

        所以,for循环遍历下标的方式就不可以的啦...

    2). 使用for in 循环.

        注意的1点是: 遍历出来的数据是字典中的Key,要取值的话,还要通过Key去取值.

         for(NSString *key in dict)

         {

            NSLog(@"%@ = %@",key,[dict objectForKey:key]);

         }

    3). 使用block来遍历字典数组.

        - (void)enumerateKeysAndObjectsUsingBlock:(void (^)(KeyType key, ObjectType obj, BOOL *stop))block

     [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {

         //key 遍历出来的键.

         //obj 遍历出来的值.

         //stop指针.

         NSLog(@"%@ = %@",key,obj);

         

         if([key isEqualToString:@"age"])

         {

            *stop = YES;

         }

     }];

     

8. NSDictionary数组存储数据的原理.

    1). 当我们往字典数组中存储键值对的.这个键值对不是挨个挨个的存储的.

    2). 当我们要往这个字典数组中存储1个键值对的时候,

        这个键值对要存储到哪1个下标中呢 ?

        根据键做1个哈希算法和数组的长度 算出1个下标来.

        然后把这个键值对存储到这个字典数组中对应下标处.

    3). 我们取值是通过key取值的.

        这个时候,仍然是根据这个Key做1个哈希算法.

        算出这个key所在的下标 让后取值.

    与NSArray的区别.

    1). NSArray是1个1个的挨个存储.

        NSDictionary不是挨个存储的.每1个键值对要存储在哪个下标处 都是通过算出来的.

        所以,存储数据的时候,肯定是NSArray的效率高1些.

    2). 取数据的时候.

        如果我们要讲数组中的所有的元素取出来.

        取的时候,肯定是NSArray快.

        NSArray挨个挨个的取就可以 而字典每取1个就要算1下.

    3). 使用场景.

        如果我们往数组中存储数据,存储进去以后,凡是要取数据都是全部取出来.使用NSArray.

    `                        如果取值的时候,只会取其中的特定的几个.使用字典数组.


-------------------------------

1. NSMutableDictionary.可变字典数组.

    1). 是NSDictionary的子类. 所以它也是以键值对的形式来存储数据.

        和父类的不同之处: 键值对可以动态的新增和删除.



2. 创建可变字典数组.

     NSMutableDictionary *dict1 =  [NSMutableDictionary new];

     NSMutableDictionary *dict2 =  [[NSMutableDictionary alloc] init];

     NSMutableDictionary *dict3 =  [NSMutableDictionary dictionary];

     上面的这些方法创建出来的可变字典的长度是0 这是有意义的.因为可以动态的新增和删除.

     NSMutableDictionary *dict4 =  [NSMutableDictionary dictionaryWithObjectsAndKeys:@"jack",@"name",@"17",@"age",nil];

    注意:

    NSMutableDictionary *dict3 = @{}; 这么做是不行的.

3. 如何新增键值对.

    - (void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>)aKey;

    值可以是任意的OC对象.

    键必须是遵守了NSCopying协议的对象. NSString就是遵守了这个协议.

    如果键重复,后新增会将前面的值覆盖掉.

    值是可以重复的


4. 删除键值对.

        [dict removeAllObjects];//全部清空.

        [dict removeObjectForKey:@"name"];//删除这个键对应的键值对.


5. 字典数组也可以持久化为1个plist文件.

    - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;

        

    //将pist文件还原为1个字典 返回值的类型NSDictionary

    //但是实际的对象,是1个可变的.

    + (nullable NSDictionary<KeyType, ObjectType> *)dictionaryWithContentsOfFile:(NSString *)path;




1. 集合的内存管理.

    集合: OC中的数组 NSArray 和 NSDictionary统称为集合.

2. 在MRC的模式下.

    将1个对象存储到集合中.

    会为这个对象的引用计数器+1.

    当集合被销毁的时候,那么就会为存储在集合中的对象发送1条release消息.

3. 在ARC模式下:

    集合的元素的类型是个强类型的指针.

   

    在ARC的模式下,使用类方法创建的对象收不了. ???????????


4. 以@[]  @{} 创建的集合,已经是被autorelease过的了.

    1). MRC模式下: 将1个对象存储到集合中,会为这个对象的引用计数器+1

                  这个集合释放,会为这个集合中的对象发送1条release消息.

    2). 在ARC的模式下: 集合的元素是强类型的指针.




1. NSFileManger是Foundation框架提供的1个类.   

     这个类作用: 用来操作磁盘上的文件 文件夹  对他们进行创建、删除、复制 拷贝 移动.....

  2. NSFileManager是1个类.

     这个类的对象是以单例模式创建的.

     如何得到NSFileManager的1个单例对象.

     掉用这个类的类方法,defaultManager 就可以得到这个类的单例对象

     NSFileManager *fileManager = [NSFileManager defaultManager];

  3. 常用方法之 判断.

     1). 判断指定的文件或者文件夹在磁盘上是否真实的存在

        - (BOOL)fileExistsAtPath:(NSString *)path;

     2).判断指定的路径是否真实的存储在我们的磁盘之上,并且判断这个路径是1个文件夹路径还是1个文件路径.

        - (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory;

        返回值:代表这个路径是否真实存在.

        参数指针: 代表这个路径是否是1个文件夹路径

     

     3). 判断指定的文件夹或者文件是否可以读取.

         - (BOOL)isReadableFileAtPath:(NSString *)path;

     4). 判断指定的文件夹或者文件是否可以写入.

         - (BOOL)isWritableFileAtPath:(NSString *)path;

     5). 判断指定的文件夹或者文件是否可以删除.

         - (BOOL)isDeletableFileAtPath:(NSString *)path

4. 常见方法之 获取信息.

    1).获取指定文件或者文件夹的属性信息.

       - (NSDictionary *)attributesOfItemAtPath:(NSString *)path error:(NSError **)error

       返回的是1个字典,如果要拿到特定的信息 通过key

    2).获取指定目录下的所有的文件和目录. 是拿到指定目录下的所有的文件和目录 所有的后代目录和文件.

       子目录的子目录的子目录 所有的都可以拿到.

       - (NSArray *)subpathsAtPath:(NSString *)path;

    3).获取指定目录下的所有的子目录和文件 不保护孙子辈.

       - (NSArray *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError **)error

5. 常见方法之 文件/目录的创建

   

    1). 在指定的目录创建文件.

        - (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr

        第1个参数: 要创建的文件的路径.

        第2个参数: 这个文件的内容.  要传递这个文件的二进制格式.

                  这个二进制的数据格式 使用NSData对象来封装.

                  NSData: 将别的格式的数据转换为二进制数据.

   

                  将字符串转换为NSData二进制的方式.调用字符串对象的

                   - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding

                   编码参数: NSUTF8StringEncoding

                  指定1个编码 就可以将字符串转换为二进制数据 存储在NSData对象之中.

                  最后再将这个二进制对象通过这个方法写入.

                  如果想创建1个空文件 第2个参数就给nil

        第3个参数: 指定创建的文件的属性.如果想要使用系统的默认值使用nil

    2). 在指定的目录创建文件夹.

        - (BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(NSDictionary *)attributes error:(NSError **)error

        第1个参数: 路径.

        第2个参数: YES,做一路创建. 如果是NO就不会做一路创建.

        第3个参数: 指定属性 nil为系统默认属性.

        第4个参数.

    3).拷贝文件.

       - (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error

   

    4).移动文件 剪切 文件的重命名. 重名的原理: 将文件移动到原来的目录并改名.

       - (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error

    5).删除文件.

       - (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error

      注意 删除的文件不会倒废纸篓 而是直接删除,所以请小心使用.










欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2