2013-08-06 74 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等自定義類,但你可以使用該類的包裝類保存那裏的價值。 –