如何使用 NSUserdefaults 为每个启动的对象创建一个密钥
Posted
技术标签:
【中文标题】如何使用 NSUserdefaults 为每个启动的对象创建一个密钥【英文标题】:How to create a key per initiated object using NSUserdefaults 【发布时间】:2015-03-29 04:55:01 【问题描述】:我有一个自定义的 NSObject,我使用管理器实例化这个对象。
我的 NSObjet 被传递到一个可变数组中,这样一旦保存方法被初始化,我就可以通过 uipickerview 访问它们的属性(名称)。
当我关闭我的应用程序时,我的所有对象都会按预期消失。
我想将我的对象保存在 NSUserDefaults 中,所以我已经在我的经理中实现了 NSUserdefaults。这是为了保存我的对象,以便在 uipickerviewcontroller 中启动应用程序时加载它们。
但是,当我加载 uipickerviewcontroller 时,我的应用程序崩溃了。 这是崩溃后的日志: 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[PacsServer encodeWithCoder:]: unrecognized selector sent to instance 0x7fd0a2e7fa20”
PacsServer.h
#import <Foundation/Foundation.h>
@interface PacsServer : NSObject
@property ( nonatomic) NSString *pacsName;
@property (nonatomic) NSString*username;
@property ( nonatomic) NSString*password;
@property (nonatomic) NSString *wadoUrl;
@property ( nonatomic) NSString *apiDirectory;
@property ( nonatomic) NSString *dataArrayIncludesUsernamePasswordWadoLoginWebServiceAndSecurity;
@end
pacsserver.m
#import "PacsServer.h"
@implementation PacsServer
@end
manager.h
#import <Foundation/Foundation.h>
@interface PacsServerManager : NSObject
+(instancetype)pacsManager ;
@property NSMutableArray *pacsServers;
@end
Manager.m
#import "PacsServerManager.h"
#import "PacsServer.h"
@implementation PacsServerManager
+(instancetype)pacsManager
static id instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
instance = [[self alloc] init];
);
return instance;
-(id) init
if(self =[super init])
PacsServer *server= [[PacsServer alloc] init];
_pacsServers = [NSMutableArray arrayWithObjects:server, nil];
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSData *serverData = [NSKeyedArchiver archivedDataWithRootObject:_pacsServers];
[standardUserDefaults setObject:serverData forKey:@"server"];
[standardUserDefaults setObject:_normalArray forKey:@"Servers" ];
[standardUserDefaults synchronize];
return self;
@end
在下面的保存方法中,我从文本字段中获取用户名、密码和其他字段。为了能够将所有这些保存到钥匙串中。
-我首先将它们保存在一个数组中,然后使用 datawithJsonObject 将此数组传递给 NSData。 然后将此数组作为 NSString 保存到钥匙串中
通过管理器添加 nsobjects
#import "AddPACSViewController.h"
#import "PacsServerManager.h"
#import "PacsServer.h"
#import <KeychainItemWrapper.h>
@interface AddPACSViewController ()
@end- (void)saveForAddPacs:(id)sender
.
.
.
.
NSString *pacsDataArray = [keychain objectForKey:(__bridge id)kSecValueData];
PacsServer *newPacsServer = [[PacsServer alloc] init];
newPacsServer.pacsName= pacsNameFromAddPacsView;
newPacsServer.dataArrayIncludesUsernamePasswordWadoLoginWebServiceAndSecurity = pacsDataArray;
[[PacsServerManager pacsManager].pacsServers addObject:newPacsServer];
[self performSegueWithIdentifier:@"Save" sender:self];
访问 uipickerview 中的对象 pickerviewcontroller.m
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
NSLog(@"Pacs data in settingsview:%@", [PacsServerManager pacsManager].pacsServers);
PacsServer *server = [[PacsServerManager pacsManager].pacsServers objectAtIndex:row];
NSString *name = server.pacsName;
NSLog(@"Servername:%@, and the data %@", server.pacsName, server.dataArrayIncludesUsernamePasswordWadoLoginWebServiceAndSecurity);
NSLog(@"%@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
return name;
任何帮助将不胜感激。
谢谢。
【问题讨论】:
【参考方案1】:您需要在这里解决几件事。
1) 异常是因为这行引起的:
NSData *serverData = [NSKeyedArchiver archivedDataWithRootObject:_pacsServers];
当您归档任何对象时,该对象需要实现<NSCoding>
协议。当您归档聚合对象(如NSArray
和NSSet
)时,数组或集合中包含的每个对象也需要实现<NSCoding>
协议。在这种情况下,PacsServer
正在被发送一个 encodeWithCoder:
消息,它没有实现。
在NSCoding
上查看this tutorial。
2) 将这些对象保存在NSUserDefaults
中真的是个好主意吗? NSUserDefaults
真的是为小信息而设计的,比如您是否应该显示帮助项目,或者这是用户第一次启动您的应用程序。也许您最好将此数据保存在单独的 .dat 文件中,或者甚至使用 CoreData 或 sqlite 之类的不同方法(如果您有大量数据)。
【讨论】:
以上是关于如何使用 NSUserdefaults 为每个启动的对象创建一个密钥的主要内容,如果未能解决你的问题,请参考以下文章
NSUserDefaults 问题(如何在启动应用程序时在需要时打开不同的 viewController)
如何使用 NSUserDefaults 将项目添加到 NSMutableArray