如何 initwithCoder 和 encodewithCoder 获取指针的值

Posted

技术标签:

【中文标题】如何 initwithCoder 和 encodewithCoder 获取指针的值【英文标题】:How to initwithCoder and encodewithCoder to get value of pointer 【发布时间】:2014-06-17 18:57:46 【问题描述】:

看来我的 initwithCoder 和 encodewithCoder 工作正常,但我在做一些愚蠢的事情。

为简单起见,我将显示我的问题的相关代码。我有几个从指针和长度获取 NSData 的对象,因此这些值被存储为 const char * 和长度。

界面如下:

@interface IDImage : NSObject <NSCoding>    
@property (nonatomic) const char *templateData;
@property (nonatomic) NSUInteger templateSize;
- (void)encodeWithCoder:(NSCoder *)coder;
- (id)initWithCoder:(NSCoder *)coder;

这里是实现:

- (void)encodeWithCoder:(NSCoder *)encoder 
    [encoder encodeBytes:(const unsigned char*)self.templateData length:self.templateSize forKey:@"templateData"];
    [encoder encodeInteger:self.templateSize forKey:@"templateSize"];


- (id)initWithCoder:(NSCoder *)decoder 
    NSUInteger length = 0;
    self = [super init];
    if (self) 
        self.templateData = (const char *)[decoder decodeBytesForKey:@"templateData" returnedLength:&length];
        self.templateSize = [decoder decodeIntegerForKey:@"templateSize"];
    
    return self;

我想我正在写出编码字节(假设 NSCoder 一直在写出第一个字符,即 templateSize)。但是当我尝试解码时,我检索到一个指向 templateData 的指针。我如何获得价值?如果我有这个值,它会只包含第一个字符吗?这意味着我有一个字符和一个长度,但没有我打算以字节为单位解码的实际数据。

当我的对象只包含第一个字符和长度时,有人可以帮我理解如何以字节为单位编码和解码数据吗?

【问题讨论】:

另外,我逐步检查了我的 initWithCoder 和 encodeWithCoder 并且值相同(如预期的那样)但在调用代码中值不同: templateToRead = [NSKeyedUnarchiver unarchiveObjectWithFile:[documentsDirectory stringByAppendingPathComponent:item]] ; 【参考方案1】:

如果您查看相关方法decodeBytesWithReturnedLength: 的文档,它会说:

如果您需要超出当前@autoreleasepool 范围的字节 块,你必须复制它们。

我假设decodeBytesForKey:returnedLength: 遵循相同的规则。所以你的代码应该是这样的:

- (id)initWithCoder:(NSCoder *)decoder 

  NSUInteger length = 0;
  self = [super init];
  if (self) 
  
    void* temp = decoder decodeBytesForKey:@"templateData" returnedLength:&length];
    void *bytes = malloc(length);
    memcpy(bytes, temp, length);
    self.templateData = bytes;
    self.templateSize = [decoder decodeIntegerForKey:@"templateSize"];
  
  return self;

然后在你的 dealloc 中添加这样的代码:

- (void) dealloc;

  if (_templateData)
    free(_templateData);
)

提示 @nil,他在文档中发现了(相当隐藏的)关于返回缓冲区临时寿命的信息。

【讨论】:

是的,在你们两个之间,我终于成功了。 请注意,如果您的对象没有 dealloc 方法,则必须添加一个并确保它释放内存缓冲区。否则会导致内存泄漏。

以上是关于如何 initwithCoder 和 encodewithCoder 获取指针的值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UIView 的子类中同时覆盖 initWithFrame: 和 initWithCoder:?

initWithCoder:被 nib 和 NSCoding 调用!

当覆盖 initWithCoder 时,总是需要调用 [super initWithCoder: coder]

方法 Swizzle encodeWithCoder/initWithCoder

initWithCoder:在 NSObject 中不可见?

覆盖 initWithCoder 时的无限循环