Por NSUserDefaults não conseguiu salvar NSMutableDictionary no iOS?
-
19-08-2019 - |
Pergunta
Eu gostaria de salvar um objeto NSMutableDictionary
em NSUserDefaults
. O tipo de chave em NSMutableDictionary
é NSString
, o tipo de valor é NSArray
, que contém uma lista de objecto que implementa NSCoding
. Por documento, NSString
e NSArray
ambos estão em conformidade com NSCoding
.
Estou recebendo este erro:
[NSUserDefaults setObject: forKey:]:. Tentativa de inserir o valor não-propriedade .... de classe NSCFDictionary
Solução
eu descobri uma alternativa, antes excepto, que codificam o objecto da raiz (objeto NSArray
) usando NSKeyedArchiver
, que termina com NSData
. Em seguida, use UserDefaults salvar o NSData
.
Quando eu precisar os dados, eu li o NSData
e uso NSKeyedUnarchiver
para converter NSData
volta para o objeto.
É um pouco complicado, porque eu preciso para converter de / para toda NSData
, mas ele simplesmente funciona.
Aqui está um exemplo por solicitação:
Salvar:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *arr = ... ; // set value
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
[defaults setObject:data forKey:@"theKey"];
[defaults synchronize];
Carga:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:@"theKey"];
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
O elemento nos instrumentos de matriz
@interface CommentItem : NSObject<NSCoding> {
NSString *value;
}
Em seguida, na implementação de CommentItem
, fornece dois métodos:
-(void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:value forKey:@"Value"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
self.value = [decoder decodeObjectForKey:@"Value"];
return self;
}
Qualquer um tem a melhor solução?
Obrigado a todos.
Outras dicas
Se você estiver salvando um objeto em padrões do usuário, todos os objetos, de forma recursiva, todo o caminho, tem de ser propriedade da lista de objetos. Em conformidade com NSCoding não significa nada NSUserDefaults
aqui-- não codificá-los automaticamente em NSData
, você tem que fazer isso mesmo. Se a sua "lista de objeto que implementa NSCoding
", os objectos que não são lista de propriedades objetos, então você vai ter que fazer algo com eles antes de salvar a padrões do usuário.
FYI as classes de lista propriedade são NSDictionary
, NSArray
, NSString
, NSDate
, NSData
e NSNumber
. Você pode escrever subclasses mutáveis ??(como NSMutableDictionary
) para as preferências do usuário, mas os objetos que você leu será sempre imutável.
Tem todas as suas chaves nas NSString
s dicionário? Eu acho que eles têm que estar em ordem para salvar o dicionário para uma lista de propriedades.
Simplest Resposta:
NSDictionary
é apenas uma objeto plist , se os chaves são NSStrings .
Então, guarde o "Key" como NSString
com stringWithFormat
.
Solução:
NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];
Benefícios:
- Ele irá adicionar String-Valor .
- Ele irá adicionar Vazio-Value quando o valor da variável é
NULL
.
Você já pensou em olhar para a implementação do Protocolo NSCoding
? Isso permitirá que você codificar e decodificar no iPhone com dois métodos simples que são implementadas com o NSCoding
. Primeiro você precisa adicionar o NSCoding
à sua classe.
Aqui está um exemplo:
Este é no arquivo .h
@interface GameContent : NSObject <NSCoding>
Em seguida, você precisará implementar dois métodos do Protocolo NSCoding.
- (id) initWithCoder: (NSCoder *)coder
{
if (self = [super init])
{
[self setFoundHotSpots:[coder decodeObjectForKey:@"foundHotSpots"]];
}
return self;
}
- (void) encodeWithCoder: (NSCoder *)coder
{
[coder encodeObject:foundHotSpots forKey:@"foundHotSpots"];
}
Confira a documentação sobre NSCoder para mais informações. Que veio em muito útil para meus projetos onde eu preciso para salvar o estado do aplicativo no iPhone, se o aplicativo é fechado e restaurá-lo de volta ao seu estado quando a sua volta.
A chave é para adicionar o protocolo para a interface e, em seguida, implementar os dois métodos que fazem parte do NSCoding
.
Espero que isso ajude!
Não há uma solução melhor. Outra opção seria apenas para salvar o objeto codificado no disco - mas que está fazendo a mesma coisa. Ambos acabam com NSData que será decodificado quando você o quer de volta.