Objective-C的数据存储和参数传递

最简单的本地数据存储——NSUserDefaults

NSUserDefaults提供了一系列方法,可以存储一些基本数据类型或对象,具体用法有以下几个方法:

  • 初始化方法:静态单例方法,获得默认的本地存储区
+(NSUserDefaults * _Nonnull) standardUserDefaults
  • 添加和修改键值
-(void) setObject:(nullable id) forKey:(nonnull NSString *)
  • 除了setObject:forKey:方法之外还有setBool、setURL、setfloat等方法,用于添加对应的键值。传入的字符串作为键名,以便于区分和在读取的时候使用。
  • 读取键值
-(id _Nullable) objectForKey:(nonnull NSString *)
  • 其中参数就是在调用setObject:forKey:时候所传入键名,同样地也有boolForKey等对用类型的方法。返回值就是之前存入的值。
  • 在存储对象时的注意事项:在存储对象时,如果不是NSData、NSArray、NSMutableArray、NSURL这样的类型,要注意必须先转化为NSData才能存储:
+(NSData * _Nonnull)archivedDataWithRootObject:(nonnull id)
  • 这个方法是NSKeyedArchiver的一个静态方法,通过这个方法可以将任意遵循NSCoding协议的对象转化为NSData。然后再将NSData存入NSUserDefault即可。
  • 读取的时候直接读取到的也是NSData数据,需要转化为原来的数据
+(id _Nullable)unarchiveObjectWithData:(nonnull NSData *)

这个方法是NSKeyedUnarchiver的静态方法,通过这个方法可以将NSData还原为原来的数据,这个方法是可失败的,返回值可能是nil。

参数传递的两种方式

  • 在多视图程序中,视图之间的参数传递显得尤为重要,刚才提到了NSUserDefaults的使用,显然这样的方式可以用于数据传递。这种传递方式比较适合较多视图的参数传递,例如所有视图都需要读取夜间模式的状态,大多数视图需要读取用户是否登陆等,这样的数据用NSUserDefaults进行保持比较合适。而只在两个视图之间的参数传递,可以使用类似于函数参数传递的方式,这种方式依赖于协议和Segue跳转时候的一个方法来实现,这个方法有如下定义:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
  • 这个方法如此重要,以至于系统在默认创建的ViewController视图类的文件中都会提到。它是在加载一个Segue的时候调用,而且是在跳转之前调用的,根据Apple官方的说明,可以使用 [segue destinationViewController]来获得跳转后的视图控制器,获得之后,可以调用这个视图控制器的方法进行参数传递。这时候推荐将该方法定义为协议。例如有如下的用法:
@protocol DataTransferDelegate <NSObject>
//该协议规定了视图之间参数传递的方式
@optional
-(void)transferBoolValue:(BOOL)state From:(id)sender;
-(void)transferString:(NSString *)str From:(id)sender;
@end
  • 然后在跳转前的视图控制器类中编写以下方法:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:@"ToLogInSegue"]) {
    //先对identifier进行判断
        LogInTestViewController *viewController=[segue destinationViewController];
    //获得跳转后的视图控制器
        [viewController transferBoolValue:([_touchidswitch isOn]) From:(self)];
    //调用用于传递参数的协议方法
    }
  }
  • 注意,因为这个方法被所有可加载的Segue所共用,所以在有多个Segue定义的时候,推荐先判断下标示符。
  • 最后,在跳转后的标识符中,使用协议方法来接收参数即可。