1

このエラーは SO に何度も表示されているようです。この問題に対する最も顕著な答えは、 RestKit 0.20 のようです — CoreData: エラー: NSManagedObject クラスで指定された初期化子を呼び出すことができませんでした

ただし、投稿された解決策は私にとってはうまくいきません。しかし、最初から始めましょう:

サーバーにファイルをアップロードしたい。応答を解析して、正常にアップロードされたことを確認したいと思います。そうでない場合は、後でもう一度試します。私のモデルには、NSNumber *sentToServerこの目的のために呼び出されるブール変数があります(CoreData では、BOOLとして保存されますNSNumber)

送信が成功するかどうかわからないため、RestKit 経由で送信する前に、エンティティを CoreData モデルに保存します。

POST リクエストが成功すると、サーバーは次のような JSON 文字列を返します。

{"id":14,"created":true}

もちろん、ID は CoreData モデルにはまだ設定されていないことに注意してください。そのため、idとの両方createdが私のモデルの新しい情報です。

これが私のモデルです:

@interface Recording : NSManagedObject

@property (nonatomic, retain) NSString * audioFilePath;
@property (nonatomic, retain) NSDate * createdAt;
@property (nonatomic, retain) NSString * deviceId;
@property (nonatomic, retain) NSString * deviceType;
@property (nonatomic, retain) NSNumber * recordingId;
@property (nonatomic, retain) NSNumber * sentToServer;

@end

そして、これが私がそれを設定する方法です:

NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"HTRecording" ofType:@"momd"]];
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"AudioModel.sqlite"];
NSError *error = nil;

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                         [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

if (![managedObjectStore addSQLitePersistentStoreAtPath:storePath
                                 fromSeedDatabaseAtPath: nil
                                      withConfiguration:nil
                                                options:options
                                                  error:&error]) {
    NSAssert(NO, @"Managed object store failed to create persistent store coordinator: %@", error);
}
[managedObjectStore createManagedObjectContexts];

// Configure MagicalRecord to use RestKit's Core Data stack
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:managedObjectStore.persistentStoreCoordinator];
[NSManagedObjectContext MR_setRootSavingContext:managedObjectStore.persistentStoreManagedObjectContext];
[NSManagedObjectContext MR_setDefaultContext:managedObjectStore.mainQueueManagedObjectContext];

NSString *databaseUrl = @"http://localhost:3000";
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:databaseUrl]];
objectManager.managedObjectStore = managedObjectStore;
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;

// Setup mapping
RKEntityMapping* recordingRequestMapping = [RKEntityMapping mappingForEntityForName:@"Recording" inManagedObjectStore:managedObjectStore];
[recordingRequestMapping addAttributeMappingsFromDictionary:@{
 @"device_id": @"deviceId",
 @"device_type": @"deviceType"     }];

RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[recordingRequestMapping inverseMapping]
                                                                               objectClass:[Recording class]
                                                                               rootKeyPath:@"recording"];
[objectManager addRequestDescriptor:requestDescriptor];

RKEntityMapping* recordingResponseMapping = [RKEntityMapping mappingForEntityForName:@"Recording" inManagedObjectStore:managedObjectStore];
[recordingResponseMapping addAttributeMappingsFromDictionary:@{
 @"created": @"sentToServer",
 @"id": @"recordingId"}];
recordingResponseMapping.identificationAttributes = @[@"recordingId"];

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:recordingResponseMapping
                                                                                   pathPattern:@"/audio.json"
                                                                                       keyPath:nil
                                                                                   statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

[objectManager addResponseDescriptor:responseDescriptor];

まず、これは非常に一般的であるべきもののセットアップ コードが驚くほど長くなります (RestKit と MagicalRecord を初期化するだけです)。しかし、私は脱線します...

アップロードプロセス全体が正常に機能します。リクエストのマッピングは適切で、添付ファイルを含め、すべてがサーバーに保存されます。ファイルはマルチパート ポスト メソッドを介して送信されるため、リクエスト マッピングにはファイルが含まれていないことに注意してください。繰り返しますが、その部分は正常に機能します。ファイルをアップロードするためのコードは次のとおりです。

RKObjectManager *manager = [RKObjectManager sharedManager];
NSMutableURLRequest *request;

request = [manager multipartFormRequestWithObject:recording
                                           method:RKRequestMethodPOST
                                             path:@"audio.json" 
                                       parameters:nil
                        constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileData:[[NSFileManager defaultManager] contentsAtPath:recording.audioFilePath]
                                    name:@"recording[audio]"
                                fileName:[recording.audioFilePath lastPathComponent]
                                mimeType:@"audio/m4a"];
    }];

RKObjectRequestOperation *operation = [manager objectRequestOperationWithRequest:request
                                                                         success:^(RKObjectRequestOperation *op, RKMappingResult *mapping) {
                                                                             NSLog(@"successfully saved file on the server");
                                                                         }
                                                                         failure:^(RKObjectRequestOperation *op, NSError *error){
                                                                             NSLog(@"some weird error");
                                                                         }];


[manager enqueueObjectRequestOperation:operation];

オブジェクトへの応答のマッピングが難しくなります。応答マッピングが一致しない場合、ログ出力には、応答を処理できなかったというエラーが含まれます (驚き)。ただし、応答マッピングが一致すると、アプリがクラッシュしますスタック トレースは次のとおりです。

#11 0x2f6482d6 in -[NSObject(NSKeyValueCoding) valueForKeyPath:] ()
#12 0x00113b9a in -[RKMappingOperation shouldSetValue:forKeyPath:usingMapping:] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMappingOperation.m:436
#13 0x00114e40 in -[RKMappingOperation applyAttributeMapping:withValue:] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMappingOperation.m:536
#14 0x00115fd4 in -[RKMappingOperation applyAttributeMappings:] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMappingOperation.m:577
#15 0x0011c988 in -[RKMappingOperation main] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMappingOperation.m:948
#16 0x2f655d0a in -[__NSOperationInternal _start:] ()
#17 0x0010cd5a in -[RKMapperOperation mapRepresentation:toObject:atKeyPath:usingMapping:metadata:] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMapperOperation.m:256
#18 0x0010b6aa in -[RKMapperOperation mapRepresentation:atKeyPath:usingMapping:] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMapperOperation.m:176
#19 0x0010ddc8 in -[RKMapperOperation mapRepresentationOrRepresentations:atKeyPath:usingMapping:] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMapperOperation.m:314
#20 0x0010e552 in -[RKMapperOperation mapSourceRepresentationWithMappingsDictionary:] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMapperOperation.m:359
#21 0x0010ee72 in -[RKMapperOperation main] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/ObjectMapping/RKMapperOperation.m:398
#22 0x2f655d0a in -[__NSOperationInternal _start:] ()
#23 0x00100e70 in -[RKObjectResponseMapperOperation performMappingWithObject:error:] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/Network/RKResponseMapperOperation.m:345
#24 0x000ff4e6 in -[RKResponseMapperOperation main] at /Users/earthnail/development/RestkitFileUpload/Pods/RestKit/Code/Network/RKResponseMapperOperation.m:297
#25 0x2f655d0a in -[__NSOperationInternal _start:] ()

デバッガーがSIGABRTin で停止する行[RKMappingOperation shouldSetValue:forKeyPath:usingMapping:]は次のとおりです。

id currentValue = [self.destinationObject valueForKeyPath:keyPath];

https://stackoverflow.com/a/13734348/487556で提案されているようにブレークポイントを設定すると、そのブレークポイントに到達しないことに注意してください。これは、応答マッピングのパスに問題がないことを意味します。

ここでいくつかのことがうまくいかないことが想像できます。

  1. RestKit は、CoreData エンティティがまだ存在しないと想定し、それを作成したいと考えています。これはエンティティの重複につながります (これは残念です!) が、モデルのすべてのフィールドがオプションであるため、クラッシュすることはありません。
  2. RestKit は ID に基づいて CoreData エンティティを見つけようとしますが (これは識別子変数であるため)、もちろん ID はまだ設定されていません。
  3. 何か他の...

助言がありますか?

4

2 に答える 2

1

あなたが尋ねてからしばらく経ち、それ以来あなたは道を見つけたかもしれませんが、私はちょうど同じ状況に遭遇し、解決策を見つけました.

この問題は、objectRequestOperationWithRequest:success:failure:NSManagedObjects を操作しているときにこのメソッドを使用することに起因しています。そのため、RestKit はマッピング操作中に通常の NSObject をインスタンス化しようとし、クラッシュにつながります。

代わりに使用してみてくださいmanagedObjectRequestOperationWithRequest:managedObjectContext:success:failure:。状況は改善されるはずです。

于 2014-04-28T09:33:31.530 に答える
0

問題は、応答の説明と要求で一致するパスにあります。それを機能させるには、それらのスラッシュが同じである必要があります。そうでない@"/audio.json"場合@"audio.json"、RestKit は一方が他方と一致することを認識しません。

于 2013-11-02T12:13:36.787 に答える