1

これは RestKit のバグですか、それとも適切に構成していませんか? 次のマッピングを使用すると、無限ループが発生します。

JSON:

[
{
    "name": "Test 1",
    "subtests": [
        {
            "name": "Subtest 1"
        },
        {
            "name": "Subtest 2"
        },
        {
            "name": "Subtest 3"
        }
    ],
    "children": ["Test 1"]
},
{
    "name": "Test 2",
    "subtests": [
        {
            "name": "Subtest 4"
        },
        {
            "name": "Subtest 5"
        },
        {
            "name": "Subtest 6"
        }
    ],
    "children": ["Test 2"]
}
]

マッピング プロバイダー:

+ (RKMapping *)testMapping
{
    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Test class]) inManagedObjectStore:[InfoDataModel sharedDataModel].objectStore];

    mapping.identificationAttributes = @[ @"name" ];

    [mapping addAttributeMappingsFromArray:@[ @"name" ]];

    [mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"children" toKeyPath:@"children" withMapping:[MappingProvider reflexiveTestMapping]]];
    [mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"subtests" toKeyPath:@"subtests" withMapping:[MappingProvider subTestMapping]]];

    return mapping;
}

+ (RKMapping *)reflexiveTestMapping
{
    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Test class]) inManagedObjectStore:[InfoDataModel sharedDataModel].objectStore];

    mapping.identificationAttributes = @[ @"name" ];

    [mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:@"name" withMapping:[MappingProvider testMapping]]];

    return mapping;
}

+ (RKMapping *)subTestMapping;
{
    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([SubTest class]) inManagedObjectStore:[InfoDataModel sharedDataModel].objectStore];

    mapping.identificationAttributes = @[ @"name" ];

    [mapping addAttributeMappingsFromArray:@[ @"name" ]];

    return mapping;    
}

私はここからそれを呼び出します:

- (IBAction)loadTestAndSubtestEntity:(id)sender {
    RKLogConfigureByName("RestKit", RKLogLevelWarning);
    RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
    RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);

    NSString *filePathComponent = [self.pathComponent     stringByAppendingPathComponent:@"test.json"];
    [[InfoDataModel sharedDataModel] importDataFromJsonFilePathComponent:filePathComponent withMapping:[MappingProvider testMapping]];
}

ハングするため、出力は生成されません。self.storePath はファイル パスで初期化されます。

- (void)importDataFromJsonFilePathComponent:(NSString *)jsonFilePathComponent withMapping:(RKMapping *)mapping
{
    if (self.storePath) {
        NSString *jsonFilePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:jsonFilePathComponent];
        MyLog(@"InfoDataModel. JSON file: %@", jsonFilePath);
        RKManagedObjectImporter *importer = [[RKManagedObjectImporter alloc] initWithManagedObjectModel:self.objectStore.managedObjectModel storePath:self.storePath];
        importer.resetsStoreBeforeImporting = NO;
        MyLog(@"InfoDataModel. Store: %@", self.storePath);

        NSError *error = nil;
        [importer importObjectsFromItemAtPath:jsonFilePath
                                  withMapping:mapping
                                      keyPath:nil
                                        error:&error];

        BOOL success = [importer finishImporting:&error];
        if (success) {
            [importer logSeedingInfo];
        }
    }
}
4

4 に答える 4

1

問題は、互いに呼び出している 2 つのメソッドがあることです。メソッドは、次の行によりtestMappingメソッドを呼び出します。reflexiveTestMapping

[mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"children" toKeyPath:@"children" withMapping:[MappingProvider reflexiveTestMapping]]];

そして、メソッドは次の行によりreflexiveTestMappingメソッドを呼び出します。testMapping

[mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:@"name" withMapping:[MappingProvider testMapping]]];

これは、マッピングとは直接関係なく、単にマッピングを作成しようとしている方法に関連する難しい循環です。

childrenJSON の関係には完全なオブジェクトではなく名前のみが含まれているため、マッピングをこの方法で作成する必要はありません。

于 2013-08-05T12:49:08.083 に答える
0

この再帰からの 1 つの「解決策」は、推定されたジャンプ (この場合は 2 つのジャンプ) に基づいて再帰呼び出しの最大数を制限することです。

+ (RKMapping *)reflexiveTestMapping
{
    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Test class]) inManagedObjectStore:[InfoDataModel sharedDataModel].objectStore];

    mapping.identificationAttributes = @[ @"name" ];

    // No more recursion calls from this point

    return mapping;
}
于 2013-08-05T11:50:21.923 に答える
0

これは私が再帰を修正した方法です:

+ (RKMapping *)testMapping
{
    RKEntityMapping *innerMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Test class]) inManagedObjectStore:[InfoDataModel sharedDataModel].objectStore];
    innerMapping.identificationAttributes = @[ @"name" ];

    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Test class]) inManagedObjectStore:[InfoDataModel sharedDataModel].objectStore];
    mapping.identificationAttributes = @[ @"name" ];
    [mapping addAttributeMappingsFromArray:@[ @"name" ]];

    [mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"children" toKeyPath:@"children" withMapping:innerMapping]];

    return mapping;
}
于 2013-08-05T15:18:42.740 に答える
0

これは私が迅速にやったことです

class var keyAll: [String] {
    return [
      "title",
      "desc"
    ]
  }

  class var objectMapping: RKObjectMapping {
    let childMapping = RKObjectMapping(forClass: Category.self)
    childMapping.addAttributeMappingsFromArray(keyAll)

    let mapping = RKObjectMapping(forClass: Category.self)
    mapping.addAttributeMappingsFromArray(keyAll)

    mapping.addPropertyMapping(RKRelationshipMapping(fromKeyPath: keyChilds, toKeyPath: keyChilds, withMapping: childMapping))
    return mapping
  }
于 2016-05-17T04:41:28.940 に答える