Objective c 取消归档自定义类时NSInvalidUnarchiveOperationException
编辑: 通过添加Objective c 取消归档自定义类时NSInvalidUnarchiveOperationException,objective-c,macos,runtime,nsdata,nskeyedunarchiver,Objective C,Macos,Runtime,Nsdata,Nskeyedunarchiver,编辑: 通过添加QCAnnonce*a=[[QCAnnonce alloc]init]
QCAnnonce*a=[[QCAnnonce alloc]init]在函数调用之前的代码中,我解决了这个问题,所以我想我“将类引入了运行时”。但是我现在有一个警告说“a”是未使用的,那么是否有一个运行时函数可以用来“将类引入运行时”
我正在尝试创建一个客户机-服务器应用程序。使用NSKeyed(Un)归档器归档和未归档对象以进行传输。我的大多数对象传输都没有任何问题,但其中一个会引发NSInvalidUnarchiveOperationException
在我放置在initWithCoder中的断点之前调用异常:
我在发送之前已经尝试过归档/取消归档,而且效果很好,所以initWithCoder不应该有问题
我尝试在我的服务器应用程序中创建一个客户端(而不是作为我的客户端在单独的应用程序中),他可以解码该对象。我看不出我的客户端和这个新客户端有什么区别,只是它们不在同一个应用程序中
我最好的猜测是这部分:
例如,委托可以加载一些代码来引入类
返回到运行时并返回类,或替换其他类
对象如果委托返回nil,则取消归档中止,方法
引发NSInvalidUnarchiveOperationException
但是我不知道“将类引入运行时”是什么意思
以下是此对象的编码/解码方法:
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
a_listeAnnonces = [aDecoder decodeObjectForKey:@"Cartes"];
a_points = [aDecoder decodeIntForKey:@"Points"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:a_listeAnnonces forKey:@"Cartes"];
[aCoder encodeInt:a_points forKey:@"Points"];
}
以下是异常消息:
2014-06-04 11:27:34.681 myApp[3693:303] *** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (QCAnnonce)
2014-06-04 11:27:34.794 myApp[3693:303] (
0 CoreFoundation 0x00007fff8937a25c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8e898e75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8937a10c +[NSException raise:format:] + 204
3 Foundation 0x00007fff8a8acdd9 _decodeObjectBinary + 2349
4 Foundation 0x00007fff8a8ac34d _decodeObject + 288
5 Foundation 0x00007fff8a8d15a5 +[NSKeyedUnarchiver unarchiveObjectWithData:] + 92
6 myApp 0x000000010001365f -[QNProtocolWrap performMethod:withArgumentDatas:onObject:] + 543
7 myApp 0x000000010001261b -[QNConnection methodCall:withArguments:] + 251
8 myApp 0x0000000100012b23 -[QNConnection connectionBaseDidRecieveNewData:] + 211
9 myApp 0x0000000100012b8b -[QNConnection connectionBaseDidRecieveNewData:] + 315
10 myApp 0x000000010000e38c -[QNConnectionBase readInput] + 204
11 myApp 0x000000010000e591 -[QNConnectionBase stream:handleEvent:] + 449
12 CoreFoundation 0x00007fff892ebc81 _signalEventSync + 385
13 CoreFoundation 0x00007fff892ebac8 _cfstream_solo_signalEventSync + 328
14 CoreFoundation 0x00007fff892eb93f _CFStreamSignalEvent + 623
15 CFNetwork 0x00007fff81e4401a _ZN29CoreReadStreamCFStreamSupport19coreStreamReadEventEP16__CoreReadStreamm + 102
16 CFNetwork 0x00007fff81e43f89 _ZN20CoreReadStreamClient25coreStreamEventsAvailableEm + 53
17 CFNetwork 0x00007fff81f77a65 _ZN14CoreStreamBase14_callClientNowEP16CoreStreamClient + 53
18 CFNetwork 0x00007fff81e43ca9 _ZN14CoreStreamBase34_streamSetEventAndScheduleDeliveryEmh + 183
19 CFNetwork 0x00007fff81e43a32 _ZN12SocketStream40dispatchSignalFromSocketCallbackUnlockedEP24SocketStreamSignalHolder + 74
20 CFNetwork 0x00007fff81e43160 _ZN12SocketStream14socketCallbackEP10__CFSocketmPK8__CFDataPKv + 206
21 CFNetwork 0x00007fff81e43062 _ZN12SocketStream22_SocketCallBack_streamEP10__CFSocketmPK8__CFDataPKvPv + 64
22 CoreFoundation 0x00007fff892eb107 __CFSocketPerformV0 + 855
23 CoreFoundation 0x00007fff892ab661 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
24 CoreFoundation 0x00007fff8929cd12 __CFRunLoopDoSources0 + 242
25 CoreFoundation 0x00007fff8929c49f __CFRunLoopRun + 831
26 CoreFoundation 0x00007fff8929bf25 CFRunLoopRunSpecific + 309
27 HIToolbox 0x00007fff89726a0d RunCurrentEventLoopInMode + 226
28 HIToolbox 0x00007fff897267b7 ReceiveNextEventCommon + 479
29 HIToolbox 0x00007fff897265bc _BlockUntilNextEventMatchingListInModeWithFilter + 65
30 AppKit 0x00007fff82a9526e _DPSNextEvent + 1434
31 AppKit 0x00007fff82a948bb -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
32 AppKit 0x00007fff82a889bc -[NSApplication run] + 553
33 AppKit 0x00007fff82a737a3 NSApplicationMain + 940
34 myApp 0x0000000100001262 main + 34
35 myApp 0x0000000100001234 start + 52
36 ??? 0x0000000000000003 0x0 + 3
)
当您试图通过NSKeyedArchiver对该类进行解码时,该类似乎没有加载到运行时
如果未加载,NSKeyedArchiver将无法找到类QCAnnound。(这就是它无法解码的原因)
要检查这一点,您可以查看NSObject协议的+(void)load
方法
在将类加载到进程的地址空间之后,运行库会立即为每个类发送此消息一次
对于作为程序可执行文件一部分的类,运行时在进程生命周期的早期发送加载消息。对于共享(动态加载)库中的类,运行库在共享库加载到进程的地址空间后立即发送加载消息
您可以通过重载+(void)load
方法并在那里设置断点来检查这一点,并在调用unarchive之前查看它是否已加载到运行时
+ (void)load {
NSLog(@"%@ loaded!", self);
}
您的修复程序[[QCAnnounceAlloc]init]之所以有效,是因为当运行时试图向类发送第一条消息时,它需要调用该类的+(void)initialize
,并在收到initialize时,进程中的类应该已经收到加载。这里的问题是运行时没有加载静态库中的所有类。由于我没有直接调用该类(只有id),因此从未加载该类
我通过在构建设置的“其他链接器标志”中添加-objC来修复它
关于这是一个好主意的原因,可以在以下内容中找到一些信息:
-objC使链接器加载库中定义Objective-C类或类别的每个对象文件
存在两个其他标志(相同的问答):
-all_load强制链接器从它看到的每个归档中加载所有对象文件,即使是那些没有Objective-C代码的文件-在Xcode 3.2及更高版本中提供了强制加载。它允许对归档加载进行更精细的控制。每个-force_load选项后面都必须有一个到归档文件的路径,该归档文件中的每个对象文件都将被加载
这里有一个有趣的问题:)您的类是在动态加载的库中定义的吗?我的类在静态库中。不会在QCannound上调用Load,但会在此库中的其他对象上调用Load。如果我想加载这个类,除了调用随机方法外,我应该怎么做?我通过在xcode中的“链接的框架和库”下添加libQC.a链接这个库。我通过在其他链接器标志中添加-objC修复了这个问题