如何使用 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

ma​​nager.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];

当您归档任何对象时,该对象需要实现&lt;NSCoding&gt; 协议。当您归档聚合对象(如NSArrayNSSet)时,数组或集合中包含的每个对象也需要实现&lt;NSCoding&gt; 协议。在这种情况下,PacsServer 正在被发送一个 encodeWithCoder: 消息,它没有实现。 在NSCoding 上查看this tutorial。

2) 将这些对象保存在NSUserDefaults 中真的是个好主意吗? NSUserDefaults 真的是为小信息而设计的,比如您是否应该显示帮助项目,或者这是用户第一次启动您的应用程序。也许您最好将此数据保存在单独的 .dat 文件中,或者甚至使用 CoreData 或 sqlite 之类的不同方法(如果您有大量数据)。

【讨论】:

以上是关于如何使用 NSUserdefaults 为每个启动的对象创建一个密钥的主要内容,如果未能解决你的问题,请参考以下文章

如何重新启动应用程序上的所有数据? [复制]

通过 plist 覆盖 NSUserDefaults 值

NSUserDefaults 问题(如何在启动应用程序时在需要时打开不同的 viewController)

如何使用 NSUserDefaults 将项目添加到 NSMutableArray

如何将 Touch ID 与 NSUserDefaults 结合使用?

如何将 NSUserDefaults 转换为 CoreData