我正在保存我从一个社交网站上获得的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];
由于我没有使用我在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];
当我在存档和取消归档时打印数据时,打印的数据是相同的。这可能是由于两个原因。
我取消归档的数据是正确的,检索方式错误,您可以通过上面的代码建议。
我在存档时保存的数据为空。这样就保存了空。
保存访问令牌是否有任何限制。可能这是空输出的原因。
我得到的输出是:
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
答案 0 :(得分:4)
您不需要任何委托方法。相反,LOAToken
应实现initWithCoder:
和encodeWithCoder:
方法,以实际保存和恢复其包含的信息。这是实现NSCoding
协议的意义。
您可能希望阅读归档文档here。
一旦您最初从Web响应或类似响应中创建了令牌,您应该使用storeInUserDefaultsWithServiceProviderName:
将其存储到用户默认值中。然后,当您想再次使用它时,请致电initWithUserDefaultsUsingServiceProviderName:
。您不需要自己进行任何编码和解码。
答案 1 :(得分: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];