Objective-C 和 NSCoding 原始数据类型,就像旧的 C 代码一样
Posted
技术标签:
【中文标题】Objective-C 和 NSCoding 原始数据类型,就像旧的 C 代码一样【英文标题】:Objective-C and NSCoding primative data type just like the old C code 【发布时间】:2012-09-17 20:45:31 【问题描述】:我有一些看起来像这样的旧 C 代码:
#include <stdio.h>
#include <strings.h>
main()
FILE *output;
struct socket_cpacket
char type; /* CP_SOCKET */
char version;
char udp_version; /* was pad2 */
char pad3;
unsigned socket;
;
struct socket_cpacket sockPack;
bzero(&sockPack,sizeof(sockPack));
sockPack.type = 27;
sockPack.version = 4;
sockPack.udp_version = 10;
sockPack.pad3 = 0;
sockPack.socket = 0;
output = fopen("/tmp/sockPack.bin", "wb");
fwrite(&sockPack, sizeof(sockPack), 1, output);
我想在 obj-c 中复制此功能,并开始使用 NSCoding 协议。
CP_Socket.h
#import <Foundation/Foundation.h>
@interface CP_Socket : NSObject <NSCoding>
@private
char type;
char version;
char udp_version;
char pad3;
unsigned int socket;
@property (readonly) char type;
@property (readonly) char version;
@property (readonly) char udp_version;
@property (readonly) char pad3;
@property unsigned int socket;
typedef enum
mTYPE = 27,
mVERSION = 4,
mUDP_VERSION = 10,
cpSocketEnum;
@end
还有 CP_Socket.m
#import "CP_Socket.h"
@implementation CP_Socket
#pragma mark ======== properties =========
@synthesize type;
@synthesize version;
@synthesize udp_version;
@synthesize pad3;
@synthesize socket;
- (id)init
NSLog(@"init");
if( !( self = [super init] ) )
return nil;
type = mTYPE;
version = mVERSION;
udp_version = mUDP_VERSION;
pad3 = 0;
socket = 0;
return self;
#pragma mark ======== Archiving and unarchiving methods =========
//
// Archives and Serializations Programming Guide for Cocoa
// http://bit.ly/PAaRsV
//
// NSCoding Protocol Reference
// http://bit.ly/PAb1Rd
//
- (void)encodeWithCoder:(NSCoder *)coder
NSLog(@"encodeWithCoder");
[coder encodeBytes:[self type] length:1 forKey:@"type"];
//[coder encodeBytes:[self version] length:1 forKey:@"version"];
//[coder encodeBytes:[self udp_version] length:1 forKey:@"udp_version"];
//[coder encodeBytes:[self pad3] length:1 forKey:@"pad3"];
//[coder encodeInt:[self socket] forKey:@"socket"];
- (id)initWithCoder:(NSCoder *)coder
NSLog(@"initWithCoder");
@end
第一个问题,[coder encodeBytes:[self type] length:1 forKey:@"type"];发出警告。不兼容的整数到指针转换将“char”发送到“const uint8_t *”类型的参数。
如何对字符进行编码?
我试过 [coder encodeInt:[self type] forKey:@"type"];但是字符!= int。
阅读代码以进一步了解其工作原理; obj-c 代码生成的文件是 280 字节,查看文件内部我看到看起来像名称损坏的类标识符。
我尝试过 NSKeyedArchiver 和 NSArchiver,结果相同。
我不知道从这里去哪里。 C 代码生成一个 8 字节的文件。我希望 obj-c 代码在使用 NSCoding 协议等一些面向对象的东西时执行相同的操作。
我觉得我必须扩展 NSCoder 对象才能完成这项工作。
任何帮助将不胜感激。
【问题讨论】:
"如何编码一个字符?"传递一个指向它的指针。char c = [self type]; [coder encodeBytes:&c length:1 forKey:@"type"];
抛出警告:发送“char *”到“const uint8_t *”(又名“const unsigned char *”)类型的参数会在点之间转换为具有不同符号的整数类型
或无符号字符,或其他。这个警告并不可怕。
【参考方案1】:
encodeBytes:length:forKey:
的第一个参数应该是指向要编码的缓冲区的指针,因此请获取 ivar 的地址:
[coder encodeBytes:&type length:1 forKey:@"type"];
或者创建一个临时变量,将属性访问的结果放入其中,并获取其地址。
使用 encodeInt:forKey:
也应该可以(使用演员表),但它会增加数据文件的大小。
如果你真的想要,你当然可以用一个类别扩展NSCoder
:
@implementation NSCoder (BTEncodeChar)
- (void)BTencodeChar: (char)c forKey: (NSString *)key
[self encodeBytes:&c length:1 forKey:key];
@end
【讨论】:
消耗这个文件的是一个 8 字节的文件。如果文件的内容与旧的 C 代码 struct->disk write 不同,则数据的使用者将忽略它。【参考方案2】:我对 NSCoding 了解不多,但 obj C 与 C 互操作就好了。将您现有的代码放入带有参数的函数中并调用它。
【讨论】:
最终可能会发生这种情况。但我想了解更多关于 obj-c 如何实现 NSCoding 协议以及如何覆盖事物以获得所需结果的更多信息。以上是关于Objective-C 和 NSCoding 原始数据类型,就像旧的 C 代码一样的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Objective-C 中保存另一个类正在使用的类对象?