1

編集:QCAnnonce* a = [[QCAnnonce alloc] init];関数呼び出しの前のどこかに In my code を追加することで問題を解決したので、「クラスをランタイムに導入した」と思います。しかし、「a」が使用されていないという警告が表示されたので、「クラスをランタイムに導入する」ために使用できるランタイム関数はありますか?

クライアント サーバー アプリケーションを作成しようとしています。オブジェクトは、NSKeyed(Un)Archiver を使用して転送のためにアーカイブおよびアーカイブ解除されます。ほとんどのオブジェクトは問題なく送信されますが、そのうちの 1 つが 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
)
4

2 に答える 2

1

NSKeyedArchiver でデコードしようとしている時点で、クラスがランタイムにロードされていないようです。

ロードされていない場合、NSKeyedArchiver はクラス QCAnnounce を見つけることができません。(そして、それがデコードできない理由です)

これを確認するには+ (void)load、NSObject プロトコルのメソッドを調べます。

ランタイムは、クラスがプロセスのアドレス空間にロードされた直後に、クラスごとに 1 回このメッセージを送信します。

プログラムの実行可能ファイルの一部であるクラスの場合、ランタイムはプロセスの存続期間の非常に早い段階でロード メッセージを送信します。共有 (動的に読み込まれる) ライブラリにあるクラスの場合、ランタイムは、共有ライブラリがプロセスのアドレス空間に読み込まれた直後に読み込みメッセージを送信します。

メソッドをオーバーロードして+(void)loadそこにブレークポイントを設定することでこれを確認し、 unarchive を呼び出す前にランタイムにロードされているかどうかを確認できます。

+ (void)load {
    NSLog(@"%@ loaded!", self);
}

修正 [[QCAnnounce alloc] init] が機能するのは、ランタイムが最初のメッセージをクラスに送信しようとするときに、+(void)initializeそのクラスを呼び出す必要があり、初期化を受け取るまでに、プロセス内のクラスがすでに負荷を受け取っている必要があるためです。

于 2014-06-05T08:29:54.303 に答える