应用沙盒

目录结构

  • Documents
    • 保存应用运行时生成的需要持久化的数据
    • iTunes同步设备时会备份该目录
    • 存储的数据非常重要,例如:可将游戏存档保存在该目录
  • Library
    • Caches
      • 保存应用运行时生成的需要持久化的数据
      • iTunes同步设备时不备份该目录
      • 一般存储体积大不需要备份的数据
    • Preferences
      • 保存应用的所有偏好设置
      • iOS的Settings(设置)应用会在该目录中查找应用的设置信息
      • iTunes同步设备时会备份该目录
  • tmp
    • 保存应用运行时所需的临时数据
    • 使用完毕后再将相应的文件从该目录删除
    • 应用没有运行时,系统也可能会清除该目录下的文件
    • iTunes同步设备时不会备份该目录

目录的常见获取方式

  • 获取沙盒根目录
      // 获取沙盒根目录
      NSString *home = NSHomeDirectory();
    
  • 获取Documents路径

      // 利用NSSearchPathForDirectoriesInDomains函数获取Documents路径
    
      // NSUserDomainMask代表从用户文件夹下找
      // YES代表展开路径中的波浪字符“~”
      NSArray *array =  NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      // 在iOS中,只有一个目录跟传入的参数匹配,所以这个集合里面只有一个元素
      NSString *documents = [array objectAtIndex:0];
    
      // 如果为NO,获取的路径是这样:~/Documents,所以建议使用YES
    
      // 如果为YES,获取的路径是这样:/Users/XXX/Library/Developer/CoreSimulator/Devices/CB5D98A8-6756-4E62-9FC6-035CD66A0F71/data/Containers/Data/Application/06C1FF2C-D808-414B-A2B1-351936C54DDD/Documents
    
  • 获取tmp路径
      NSString *tmp = NSTemporaryDirectory();
    
  • 获取Library/Caches路径
      // 类似获取Documents路径,只要将NSUserDomainMask换成NSCachesDirectory
      NSArray *array =  NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSCachesDirectory, YES);
      NSString *documents = [array objectAtIndex:0];
    
  • Library/Preference目录里的数据是通过NSUserDefaults类来操作的

偏好设置

  • 写入偏好设置

      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      [defaults setObject:@"itcast" forKey:@"username"];
      [defaults setFloat:18.0f forKey:@"text_size"];
      [defaults setBool:YES forKey:@"auto_login"];
    
      // 同步偏好设置,立即写入磁盘
      [defaults synchornize];
    
  • 读取偏好设置
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      NSString *username = [defaults stringForKey:@"username"];
      float textSize = [defaults floatForKey:@"text_size"];
      BOOL autoLogin = [defaults boolForKey:@"auto_login"];
    

plist

  • NSString、NSDictionary、NSArray、NSData、NSNumber等类型,就可以使用writeToFile:atomically:方法直接将对象写到属性列表文件中
  • 上面这些类型加载plist文件是通过方法xxxWithContentsOfFile:

归档

  • 如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,直接可以用NSKeyedArchiver进行归档和解档
  • 不是所有的对象都可以直接用这种方法进行归档,只有遵守了<NSCoding>协议的对象才可以
  • <NSCoding>协议有2个方法
    • encodeWithCoder
      • 使用encodeObject:forKey:方法归档实例变量
    • initWithCoder
      • 使用decodeObject:forKey方法解档实例变量
  • NSString、NSDictionary、NSArray、NSData、NSNumber等类型的归档和解档
    • 归档:archiveRootObject:toFile:
    • 解档:unarchiveObjectWithFile:
  • 自定义对象的归档和解档

    • 遵守<NSCoding>协议,实现协议方法

      @interface Person : NSObject<NSCoding>
      @property (nonatomic, copy) NSString *name;
      @property (nonatomic, assign) int age;
      @property (nonatomic, assign) float height;
      @end
      
      @implementation Person
      // 归档
      -(void)encodeWithCoder:(NSCoder *)encoder
      {
        [encoder encodeObject:self.name forKey:@"name"];
        [encoder encodeInt:self.age forKey:@"age"];
        [encoder encodeFloat:self.height forKey:@"height"];
      }
      // 解档
      -(id)initWithCoder:(NSCoder *)decoder
      {
        self.name = [decoder decodeObjectForKey:@"name"];
        self.age = [decoder decodeIntForKey:@"age"];
        self.height = [decoder decodeFloatForKey:@"height"];
        return self;
      }
      @end
      
      // ***************调用代码***************
      
      // 归档
      Person *person = [[[Person alloc] init] autorelease];
      person.name = @"MJ";
      person.age = 27;
      person.height = 1.83f;
      [NSKeyedArchiver archiveRootObject:person toFile:path];
      // 解档
      Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
      
  • NSKeyedArchiver归档对象的注意事项

    • 如果父类也遵守了NSCoding协议,应该在encodeWithCoder:方法中加上一句[super encodeWithCode:encode];确保继承的实例变量也能被归档
    • 如果父类也遵守了NSCoding协议,应该在initWithCoder:方法中加上一句self = [super initWithCoder:decoder];确保继承的实例变量也能被恢复解档
  • 多个对象写入到同一个文件中,使用NSMutableData

    • 归档过程

      // 新建一块可变数据区
      NSMutableData *data = [NSMutableData data];
      
      // 将数据区连接到一个NSKeyedArchiver对象
      NSKeyedArchiver *archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
      
      // 开始存档对象,存档的数据都会存储到NSMutableData中
      [archiver encodeObject:person1 forKey:@"person1"];
      [archiver encodeObject:person2 forKey:@"person2"];
      
      // 存档完毕(一定要调用这个方法)
      [archiver finishEncoding];
      
      // 将存档的数据写入文件
      [data writeToFile:path atomically:YES];
      
    • 解码过程

      // 从文件中读取数据
      NSData *data = [NSData dataWithContentsOfFile:path];
      
      // 根据数据,解析成一个NSKeyedUnarchiver对象
      NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
      
      Person *person1 = [unarchiver decodeObjectForKey:@"person1"];
      Person *person2 = [unarchiver decodeObjectForKey:@"person2"];
      
      // 恢复完毕
      [unarchiver finishDecoding];
      
  • 利用归档实现对对象的深度复制

      // 临时存储person1的数据
      NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];
      // 解析data,生成一个新的Person对象
      Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    
      // 分别打印内存地址
      NSLog(@"person1:0x%x", person1); // person1:0x7177a60
      NSLog(@"person2:0x%x", person2); // person2:0x7177cf0
    

results matching ""

    No results matching ""