2013-08-06 30 views
0

我正在保存从一个社交网站获得的AccessToken。当我保存这个时,我知道我们不能直接在iOS SDK中保存非属性值。如何使用NSUserDefaults在iOS中保存非属性值?

然后从教程中我开始知道我应该实现NSCoding类。然后我做到了。

NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:self.accessToken]; 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    [defaults setObject:myEncodedObject forKey:@"myEncodedObjectKey"]; 
    [defaults synchronize]; 

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    NSData *myEncodedObject = [defaults objectForKey:@"myEncodedObjectKey"]; 
      LOAToken *obj = (LOAToken *)[NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject]; 

我实现了NSCoding代表,但我不知道如何实现delegate methods。然后当我运行此代码时出现错误

`"-[LOAToken encodeWithCoder:]: unrecognized selector sent to instance 0xa2bb970" 

我无法实现NSCoding以及我的代码。有什么建议么?还有没有其他方式来存储非属性值,如AccessToken供进一步使用。

编辑:

我正在LinkedIn的这种访问令牌和希望存储这样的:

self.accessToken = [[LOAToken alloc] initWithHTTPResponseBody:responseBody]; 


     // The accessToken Printed....Here I have the AccessToken Value. 
     NSLog(@"Access===%@",self.accessToken); 

     NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:self.accessToken]; 
     NSLog(@"myEncodedObject===%@",myEncodedObject); 
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
     [defaults setObject:myEncodedObject forKey:@"myEncodedObjectKey"]; 
     [defaults synchronize]; 

这是越来越坠毁,因为我没有使用过NSCoding实现我在LOAToken做你建议的班​​级。

我在LAToken类中做了一个变量值并实现了这两个方法。

-(void)encodeWithCoder:(NSCoder *)encoder 
{ 
    [encoder encodeObject:value forKey:@"Value"]; 
} 

-(id)initWithCoder:(NSCoder *)decoder 
{ 
    self.value = [decoder decodeObjectForKey:@"Value"]; 
    return self; 
} 

然后,当检索我使用这个。

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    NSData *myEncodedObject = [defaults objectForKey:@"myEncodedObjectKey"]; 
    LOAToken *obj = (OAToken *)[NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject]; 

当我在两个归档和取消存档的时间,然后打印数据打印的数据是一样。这可能是由于两个原因。

  1. 我已经取消存档的数据是正确的,检索的方式是错误的,您可以通过我上面的代码建议。

  2. 我在归档时保存的数据为空。因此保存了空值。

保存访问令牌是否有任何限制。可能是这可能是空输出的原因。

这我得到的输出是这样的:

oauth_token "(null)" oauth_token_secret "(null)" oauth_verifier "(null)" 

文本"oauth_token""oauth_token_secret""oauth_verifier"从未来的accessToken但它们的值是零。

编辑2:这是LinkedIn的OAToken类哪里我得到我传递的编码方法

OAToken访问Token.The同样的道理。^ h

#import <Foundation/Foundation.h> 

@interface OAToken : NSObject { 
@protected 
    NSString *key; 
    NSString *secret; 
    NSString *session; 
    NSString *verifier; 
    NSNumber *duration; 
    NSMutableDictionary *attributes; 
    NSDate *created; 
    BOOL renewable; 
    BOOL forRenewal; 

    OAToken *value; 
} 
@property(retain, readwrite) NSString *key; 
@property(retain, readwrite) NSString *secret; 
@property(retain, readwrite) NSString *session; 
@property(retain, readwrite) NSString *verifier; 
@property(retain, readwrite) NSNumber *duration; 
@property(retain, readwrite) NSMutableDictionary *attributes; 
@property(readwrite, getter=isForRenewal) BOOL forRenewal; 
@property (nonatomic,retain) OAToken *value; 

- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret; 
- (id)initWithKey:(NSString *)aKey 
      secret:(NSString *)aSecret 
      session:(NSString *)aSession 
     verifier:(NSString *)aVerifier 
     duration:(NSNumber *)aDuration 
     attributes:(NSMutableDictionary *)theAttributes 
      created:(NSDate *)creation 
     renewable:(BOOL)renew; 

- (id)initWithHTTPResponseBody:(NSString *)body; 

- (id)initWithUserDefaultsUsingServiceProviderName:(NSString *)provider prefix:(NSString *)prefix; 
- (int)storeInUserDefaultsWithServiceProviderName:(NSString *)provider prefix:(NSString *)prefix; 

- (BOOL)isValid; 

- (void)setAttribute:(NSString *)aKey value:(NSString *)aValue; 
- (NSString *)attribute:(NSString *)aKey; 
- (void)setAttributesWithString:(NSString *)aAttributes; 
- (NSString *)attributeString; 

- (BOOL)hasExpired; 
- (BOOL)isRenewable; 
- (void)setDurationWithString:(NSString *)aDuration; 
- (void)setVerifierWithUrl:(NSURL *)aURL; 
- (BOOL)hasAttributes; 
- (NSMutableDictionary *)parameters; 

- (BOOL)isEqualToToken:(OAToken *)aToken; 

+ (void)removeFromUserDefaultsWithServiceProviderName:(const NSString *)provider prefix:(const NSString *)prefix; 

@end 

OAToken.m

#import "NSString+URLEncoding.h" 
#import "OAToken.h" 

@interface OAToken (Private) 

+ (NSString *)settingsKey:(const NSString *)name provider:(const NSString *)provider prefix:(const NSString *)prefix; 
+ (id)loadSetting:(const NSString *)name provider:(const NSString *)provider prefix:(const NSString *)prefix; 
+ (void)saveSetting:(NSString *)name object:(id)object provider:(const NSString *)provider prefix:(const NSString *)prefix; 
+ (NSNumber *)durationWithString:(NSString *)aDuration; 
+ (NSMutableDictionary *)attributesWithString:(NSString *)theAttributes; 

@end 

@implementation OAToken 

@synthesize key, secret, session, verifier, duration, attributes, forRenewal; 
@synthesize value; 

#pragma mark Encode 

-(void)encodeWithCoder:(NSCoder *)encoder 
{ 
    // This prints the value.... 
    NSLog(@"value===%@",self.value); 
    [encoder encodeObject:self.value forKey:@"Value"]; 
} 

-(id)initWithCoder:(NSCoder *)decoder 
{ 
    OAToken *hell= [decoder decodeObjectForKey:@"Value"]; 
    // This don't have the value.It is null. 
    NSLog(@"hell===%@",hell); 

    return self; 
} 

#pragma mark init 

- (id)init { 
    return [self initWithKey:nil secret:nil]; 
} 

- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret { 
    return [self initWithKey:aKey secret:aSecret session:nil verifier:nil duration:nil 
        attributes:nil created:nil renewable:NO]; 
} 



- (id)initWithKey:(NSString *)aKey 
      secret:(NSString *)aSecret 
      session:(NSString *)aSession 
     verifier:(NSString *)aVerifier 
     duration:(NSNumber *)aDuration 
     attributes:(NSMutableDictionary *)theAttributes 
      created:(NSDate *)creation 
     renewable:(BOOL)renew 
{ 
    [super init]; 
    self.key = aKey; 
    self.secret = aSecret; 
    self.session = aSession; 
    self.verifier = aVerifier; 
    self.duration = aDuration; 
    self.attributes = theAttributes; 
    created = [creation retain]; 
    renewable = renew; 
    forRenewal = NO; 

    return self; 
} 

- (void)setVerifierWithUrl:(NSURL *)aURL 
{ 
    NSString *query = [aURL query]; 
    NSArray *pairs = [query componentsSeparatedByString:@"&"]; 

    for (NSString *pair in pairs) 
    { 
     NSArray *elements = [pair componentsSeparatedByString:@"="]; 
     if ([[elements objectAtIndex:0] isEqualToString:@"oauth_verifier"]) 
     { 
      self.verifier = [elements objectAtIndex:1]; 
     } 
    } 
} 

- (id)initWithHTTPResponseBody:(const NSString *)body 
{ 
    NSString *aKey = nil; 
    NSString *aSecret = nil; 
    NSString *aSession = nil; 
    NSString *aVerifier = nil; 
    NSNumber *aDuration = nil; 
    NSDate *creationDate = nil; 
    NSMutableDictionary *attrs = nil; 
    BOOL renew = NO; 
    NSArray *pairs = [body componentsSeparatedByString:@"&"]; 

    for (NSString *pair in pairs) 
    { 
     NSArray *elements = [pair componentsSeparatedByString:@"="]; 
     if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token"]) 
     { 
      aKey = [elements objectAtIndex:1]; 
     } 
     else if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token_secret"]) 
     { 
      aSecret = [elements objectAtIndex:1]; 
     } 
     else if ([[elements objectAtIndex:0] isEqualToString:@"oauth_verifier"]) 
     { 
      aVerifier = [elements objectAtIndex:1]; 
     } 
     else if ([[elements objectAtIndex:0] isEqualToString:@"oauth_session_handle"]) 
     { 
      aSession = [elements objectAtIndex:1]; 
     } 
     else if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token_duration"]) 
     { 
      aDuration = [[self class] durationWithString:[elements objectAtIndex:1]]; 
      creationDate = [NSDate date]; 
     } 
     else if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token_attributes"]) 
     { 
      attrs = [[self class] attributesWithString:[[elements objectAtIndex:1] decodedURLString]]; 
     } 
     else if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token_renewable"]) 
     { 
      NSString *lowerCase = [[elements objectAtIndex:1] lowercaseString]; 
      if ([lowerCase isEqualToString:@"true"] || [lowerCase isEqualToString:@"t"]) { 
       renew = YES; 
      } 
     } 
    } 

    value=[self initWithKey:aKey 
           secret:aSecret 
           session:aSession 
           verifier:aVerifier 
           duration:aDuration 
          attributes:attrs 
           created:creationDate 
          renewable:renew]; 

    return [self initWithKey:aKey 
         secret:aSecret 
        session:aSession 
        verifier:aVerifier 
        duration:aDuration 
        attributes:attrs 
        created:creationDate 
        renewable:renew]; 
} 

- (id)initWithUserDefaultsUsingServiceProviderName:(const NSString *)provider prefix:(const NSString *)prefix { 
    [super init]; 
    self.key = [OAToken loadSetting:@"key" provider:provider prefix:prefix]; 
    self.secret = [OAToken loadSetting:@"secret" provider:provider prefix:prefix]; 
    self.session = [OAToken loadSetting:@"session" provider:provider prefix:prefix]; 
    self.verifier = [OAToken loadSetting:@"verifier" provider:provider prefix:prefix]; 
    self.duration = [OAToken loadSetting:@"duration" provider:provider prefix:prefix]; 
    self.attributes = [OAToken loadSetting:@"attributes" provider:provider prefix:prefix]; 
    created = [OAToken loadSetting:@"created" provider:provider prefix:prefix]; 
    renewable = [[OAToken loadSetting:@"renewable" provider:provider prefix:prefix] boolValue]; 

    if (![self isValid]) { 
     [self autorelease]; 
     return nil; 
    } 

    return self; 
} 

#pragma mark dealloc 

- (void)dealloc { 
    self.key = nil; 
    self.secret = nil; 
    self.duration = nil; 
    self.attributes = nil; 
    [super dealloc]; 
} 

#pragma mark settings 

- (BOOL)isValid { 
    return (key != nil && ![key isEqualToString:@""] && secret != nil && ![secret isEqualToString:@""]); 
} 

- (int)storeInUserDefaultsWithServiceProviderName:(const NSString *)provider prefix:(const NSString *)prefix { 
    [OAToken saveSetting:@"key" object:key provider:provider prefix:prefix]; 
    [OAToken saveSetting:@"secret" object:secret provider:provider prefix:prefix]; 
    [OAToken saveSetting:@"created" object:created provider:provider prefix:prefix]; 
    [OAToken saveSetting:@"duration" object:duration provider:provider prefix:prefix]; 
    [OAToken saveSetting:@"session" object:session provider:provider prefix:prefix]; 
    [OAToken saveSetting:@"verifier" object:verifier provider:provider prefix:prefix]; 
    [OAToken saveSetting:@"attributes" object:attributes provider:provider prefix:prefix]; 
    [OAToken saveSetting:@"renewable" object:renewable ? @"t" : @"f" provider:provider prefix:prefix]; 

    [[NSUserDefaults standardUserDefaults] synchronize]; 
    return(0); 
} 

#pragma mark duration 

- (void)setDurationWithString:(NSString *)aDuration { 
    self.duration = [[self class] durationWithString:aDuration]; 
} 

- (BOOL)hasExpired 
{ 
    return created && [created timeIntervalSinceNow] > [duration intValue]; 
} 

- (BOOL)isRenewable 
{ 
    return session && renewable && created && [created timeIntervalSinceNow] < (2 * [duration intValue]); 
} 


#pragma mark attributes 

- (void)setAttribute:(const NSString *)aKey value:(const NSString *)aAttribute { 
    if (!attributes) { 
     attributes = [[NSMutableDictionary alloc] init]; 
    } 
    [attributes setObject: aAttribute forKey: aKey]; 
} 

- (void)setAttributes:(NSMutableDictionary *)theAttributes { 
    [attributes release]; 
    if (theAttributes) { 
     attributes = [[NSMutableDictionary alloc] initWithDictionary:theAttributes]; 
    }else { 
     attributes = nil; 
    } 

} 

- (BOOL)hasAttributes { 
    return (attributes && [attributes count] > 0); 
} 

- (NSString *)attributeString { 
    if (![self hasAttributes]) { 
     return @""; 
    } 

    NSMutableArray *chunks = [[NSMutableArray alloc] init]; 
    for(NSString *aKey in self->attributes) { 
     [chunks addObject:[NSString stringWithFormat:@"%@:%@", aKey, [attributes objectForKey:aKey]]]; 
    } 
    NSString *attrs = [chunks componentsJoinedByString:@";"]; 
    [chunks release]; 
    return attrs; 
} 

- (NSString *)attribute:(NSString *)aKey 
{ 
    return [attributes objectForKey:aKey]; 
} 

- (void)setAttributesWithString:(NSString *)theAttributes 
{ 
    self.attributes = [[self class] attributesWithString:theAttributes]; 
} 

- (NSMutableDictionary *)parameters 
{ 
    NSMutableDictionary *params = [[[NSMutableDictionary alloc] init] autorelease]; 

    if (key) 
    { 
     [params setObject:key forKey:@"oauth_token"]; 
     if ([self isForRenewal]) 
     { 
      [params setObject:session forKey:@"oauth_session_handle"]; 
     } 
    } 
    else 
    { 
     if (duration) 
     { 
      [params setObject:[duration stringValue] forKey: @"oauth_token_duration"]; 
     } 
     if ([attributes count]) 
     { 
      [params setObject:[self attributeString] forKey:@"oauth_token_attributes"]; 
     } 
    } 

    if (verifier) 
    { 
     [params setObject:verifier forKey:@"oauth_verifier"]; 
    } 
    return params; 
} 

#pragma mark comparisions 

- (BOOL)isEqual:(id)object { 
    if([object isKindOfClass:[self class]]) { 
     return [self isEqualToToken:(OAToken *)object]; 
    } 
    return NO; 
} 

- (BOOL)isEqualToToken:(OAToken *)aToken { 
    /* Since ScalableOAuth determines that the token may be 
    renewed using the same key and secret, we must also 
    check the creation date */ 
    if ([self.key isEqualToString:aToken.key] && 
     [self.secret isEqualToString:aToken.secret]) { 
     /* May be nil */ 
     if (created == aToken->created || [created isEqualToDate:aToken->created]) { 
      return YES; 
     } 
    } 

    return NO; 
} 

#pragma mark class_functions 

+ (NSString *)settingsKey:(NSString *)name provider:(NSString *)provider prefix:(NSString *)prefix { 
    return [NSString stringWithFormat:@"OAUTH_%@_%@_%@", provider, prefix, [name uppercaseString]]; 
} 

+ (id)loadSetting:(NSString *)name provider:(NSString *)provider prefix:(NSString *)prefix { 
    return [[NSUserDefaults standardUserDefaults] objectForKey:[self settingsKey:name 
                     provider:provider 
                      prefix:prefix]]; 
} 

+ (void)saveSetting:(NSString *)name object:(id)object provider:(NSString *)provider prefix:(NSString *)prefix { 
    [[NSUserDefaults standardUserDefaults] setObject:object forKey:[self settingsKey:name 
                      provider:provider 
                       prefix:prefix]]; 
} 

+ (void)removeFromUserDefaultsWithServiceProviderName:(NSString *)provider prefix:(NSString *)prefix { 
    NSArray *keys = [NSArray arrayWithObjects:@"key", @"secret", @"created", @"duration", @"session", @"verifier", @"attributes", @"renewable", nil]; 
    for(NSString *name in keys) { 
     [[NSUserDefaults standardUserDefaults] removeObjectForKey:[OAToken settingsKey:name provider:provider prefix:prefix]]; 
    } 
} 

+ (NSNumber *)durationWithString:(NSString *)aDuration { 
    NSUInteger length = [aDuration length]; 
    unichar c = toupper([aDuration characterAtIndex:length - 1]); 
    int mult; 
    if (c >= '0' && c <= '9') { 
     return [NSNumber numberWithInt:[aDuration intValue]]; 
    } 
    if (c == 'S') { 
     mult = 1; 
    } else if (c == 'H') { 
     mult = 60 * 60; 
    } else if (c == 'D') { 
     mult = 60 * 60 * 24; 
    } else if (c == 'W') { 
     mult = 60 * 60 * 24 * 7; 
    } else if (c == 'M') { 
     mult = 60 * 60 * 24 * 30; 
    } else if (c == 'Y') { 
     mult = 60 * 60 * 365; 
    } else { 
     mult = 1; 
    } 

    return [NSNumber numberWithInt: mult * [[aDuration substringToIndex:length - 1] intValue]]; 
} 

+ (NSMutableDictionary *)attributesWithString:(NSString *)theAttributes { 
    NSArray *attrs = [theAttributes componentsSeparatedByString:@";"]; 
    NSMutableDictionary *dct = [[NSMutableDictionary alloc] init]; 
    for (NSString *pair in attrs) { 
     NSArray *elements = [pair componentsSeparatedByString:@":"]; 
     [dct setObject:[elements objectAtIndex:1] forKey:[elements objectAtIndex:0]]; 
    } 
    return [dct autorelease]; 
} 

#pragma mark description 

- (NSString *)description { 
    return [NSString stringWithFormat:@"oauth_token \"%@\" oauth_token_secret \"%@\" oauth_verifier \"%@\"", key, secret, verifier]; 
} 

@end 
+0

你的类必须支持NSCoding协议。那么只有你可以使用的NSKeyedArchiver – Exploring

回答

4

你不需要任何委托方法。相反,LOAToken应实施initWithCoder:encodeWithCoder:方法,以实际保存和恢复其中包含的信息。这是执行协议的含义。

您可能希望归档文档here的读取。


一旦你开始从你应该使用storeInUserDefaultsWithServiceProviderName:将它保存到用户的默认网页响应或类似的创建您的令牌。然后,当你想再次使用它时,请致电initWithUserDefaultsUsingServiceProviderName:。你不需要自己做任何编码和解码。

+0

感谢response.I已经摆脱了错误,但这个标记是在我收到result.What缺少的是这样的:组oauth_token“(空)” oauth_token_secret“(空)” oauth_verifier“( null)“。任何线索我错在哪里? –

+0

您可能想要创建一个显示编码方法的新问题。 – Wain

+0

我已经用解释更新了我的问题。请给我建议一个出路。 –

0

要取消归档数据

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
NSData *data = [defaults objectForKey:@"key"]; 
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 

归档数据

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];  
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array]; 
[defaults setValue:data forKey:@"key"]; 
[defaults synchronize]; 
+0

你不能保存像uiview等自定义类,但你可以使用该类的包装类保存那里的价值。 –