使用单例子类进行NSCoding

时间:2014-07-02 12:40:38

标签: objective-c nscoding

我有许多派生类,它们的公共基类符合NSCoding。我希望能够轻松编码各种派生类的NSArray持有实例。

@interface Base : NSObject <NSCoding>
@end

@interface DerivedSingleton : Base
+(instancetype) sharedInstance;
@end

@interface DerivedNonSingleton : Base
@end

派生单例在运行系统中应该只有一个实例。它实际上没有任何状态可以在编码器中编码。它的实例是使用+(void) initialize类方法创建的。

DerivedSingleton *sharedInstance;

@implementation DerivedSingleton
+(void) initialize
{
  sharedInstance = [DerivedSingleton new];
}

+(instancetype) sharedInstance
{
  return sharedInstance;
}
@end

所以,如果我现在创建一个包含类实例的数组,并对其进行编码:

NSArray *const array = @[
  [DerivedSingleton sharedInstance], 
  [DerivedNonSingleton new], 
  [DerivedNonSingleton new]];

NSData *const arrayData = [NSKeyedArchiver archivedDataWithRootObject: array];

当我稍后解码它时,我需要引用共享单例来解码为共享单例的引用...

NSArray *const decodedArray = [NSKeyedUnarchiver unarchiveObjectWithData: arrayData];
[decodedArray objectAtIndex: 0] == [DerivedSingleton sharedInstance];

我注意到NSCoding协议要求我为单例实现initWithCoder:,但在解码期间,我希望此类提供共享实例,而不是新的alloc ed对象

2 个答案:

答案 0 :(得分:1)

这样的事情应该有效

- (instancetype)initWithCoder:(NSCoder *)decoder
{
    self = [super init];

    return [self.class shared];
}

答案 1 :(得分:0)

我会用单身人士做类似的事情:

的.h

#import <Foundation/Foundation.h>

#pragma mark - Interface

@interface SerializableSingleton : NSObject <NSCoding>

#pragma mark - Class methods

#pragma mark - Shared instance

+ (instancetype)sharedInstance;

@end

的.m

#import "SerializableSingleton.h"

#pragma mark - Reference

static id _serializableSingletonSharedInstance = nil;

#pragma mark - Implementation

@implementation SerializableSingleton

#pragma mark - Class methods

#pragma mark - Shared instance

+ (instancetype)sharedInstance {

    @synchronized([self class]) {
        if (_serializableSingletonSharedInstance == nil) {
            _serializableSingletonSharedInstance = [[[self class] alloc] init];
        }
    }

    return _serializableSingletonSharedInstance;
}

#pragma mark - Instance methods

#pragma mark - <NSCoding>

- (id)initWithCoder:(NSCoder *)aDecoder {
    @synchronized([self class]) {
        if (_serializableSingletonSharedInstance == nil) {
            if (self = [super init]) {
                // decode the desired data...
            }
            _serializableSingletonSharedInstance = self;
        }
    }
    return _serializableSingletonSharedInstance;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    // encode the desired data
}

@end