0

我正在保存AccessToken从一个社交网络网站获得的内容。当我保存它时,我知道我们无法直接保存 iOS SDK 中的非属性值。

然后从教程中我知道我应该实现这个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];

由于我没有使用您NSCodingLOAToken课堂上建议的实现,因此这已经崩溃了。

我在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.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
4

2 回答 2

4

您不需要任何委托方法。相反,LOAToken应该实现initWithCoder:encodeWithCoder:方法来实际保存和恢复它包含的信息。这就是实现NSCoding协议的意义。

您可能想在此处阅读归档文档。


一旦您最初从 Web 响应或类似的响应中创建了您的令牌,您应该使用storeInUserDefaultsWithServiceProviderName:它来将其存储到用户默认值中。然后,当您想再次使用它时,请调用initWithUserDefaultsUsingServiceProviderName:. 您不需要自己进行任何编码和解码。

于 2013-08-06T13:36:46.773 回答
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];
于 2013-08-06T13:41:23.843 回答