如何使用 RKMappingOperation 将本地 NSDictionary 映射到自定义对象?

Posted

技术标签:

【中文标题】如何使用 RKMappingOperation 将本地 NSDictionary 映射到自定义对象?【英文标题】:How to map local NSDictionary into a custom Object using RKMappingOperation? 【发布时间】:2015-11-28 10:11:57 【问题描述】:
RJobObject * jobObj = [RJobObject new];

RKMappingOperation *mappingOperation = [[RKMappingOperation alloc] initWithSourceObject:jobDictionary destinationObject:jobObj mapping:[RJobObject mapping]];

mappingOperation.dataSource = (id)jobObj;
[mappingOperation start];


jobDictionary structure:
NSDictionary *msg1 = @
                       @"id" : @"dfcd",
                       @"message" : @"ndjfcdfcd"
                       ;
NSDictionary *msg2 = @
                       @"id" : @"fjvdfv",
                       @"message" : @"kjndcdovc"
                       ;
NSDictionary *msg3 = @
                       @"id" : @"fce",
                       @"message" : @"dfcdf"
                       ;

NSArray *msgsArray = [NSArray arrayWithObjects:msg1, msg2,msg3, nil];

NSMutableDictionary * jobDictionary = [NSMutableDictionary dictionaryWithDictionary:@@"id" : @"Sourabh pant",
                                                                            @"title": @"http://www.google.com"
                                                                            ];

[jobDictionary setObject:msgsArray forKey:@"messages"];

/.................................................. ........../

RJobObject is the custom object:
@property (nonatomic) NSString * id;
@property (nonatomic) long long duration;
@property (nonatomic) NSString * title;
@property (nonatomic) NSString * image;
@property (nonatomic) NSString * secret;
@property (nonatomic) NSInteger unreadCount;
@property (nonatomic) NSArray * messages;

如果 jobDictionary 包含消息,这会在 Rrestkit 内部造成崩溃。如果 jobDictionary 中的消息数组为空,则代码运行正常。 所以总结一下消息数组没有被映射。

堆栈跟踪 2015-11-28 15:59:22.808 检查休息套件[35951:3402596] -

[RJobObject mappingOperation:targetObjectForRepresentation:withMapping:inRelationship:]: unrecognized selector sent to instance 0x79f96270
2015-11-28 16:00:48.987 Checking Rest Kit[35951:3402596] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[RJobObject mappingOperation:targetObjectForRepresentation:withMapping:inRelationship:]: unrecognized selector sent to instance 0x79f96270'
*** First throw call stack:
(
    0   CoreFoundation                      0x018e3a14 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x013a2e02 objc_exception_throw + 50
    2   CoreFoundation                      0x018ecd63 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
    3   CoreFoundation                      0x0182a6bd ___forwarding___ + 1037
    4   CoreFoundation                      0x0182a28e _CF_forwarding_prep_0 + 14
    5   Checking Rest Kit                   0x00142f48 -[RKMappingOperation destinationObjectForMappingRepresentation:parentRepresentation:withMapping:inRelationship:] + 1704
    6   Checking Rest Kit                   0x00149885 __64-[RKMappingOperation mapOneToManyRelationshipWithValue:mapping:]_block_invoke + 149
    7   CoreFoundation                      0x018152e9 __53-[__NSArrayI enumerateObjectsWithOptions:usingBlock:]_block_invoke + 73
    8   CoreFoundation                      0x01815182 -[__NSArrayI enumerateObjectsWithOptions:usingBlock:] + 162
    9   CoreFoundation                      0x017ff835 -[NSArray enumerateObjectsUsingBlock:] + 53
    10  Checking Rest Kit                   0x0014920b -[RKMappingOperation mapOneToManyRelationshipWithValue:mapping:] + 2763
    11  Checking Rest Kit                   0x0014b4fb -[RKMappingOperation applyRelationshipMappings] + 6283
    12  Checking Rest Kit                   0x0014d7db -[RKMappingOperation main] + 4075
    13  Checking Rest Kit                   0x0014c7dd -[RKMappingOperation start] + 45
    14  Checking Rest Kit                   0x000ab866 -[ViewController jobObjectFromJobDictionary:] + 310
    15  Checking Rest Kit                   0x000ab6d5 -[ViewController fetchJobFromDbForId:] + 85
    16  Checking Rest Kit                   0x000ab566 -[ViewController viewDidLoad] + 918
    17  UIKit                               0x01e3b2ae -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 44
    18  UIKit                               0x01e3fdce -[UIViewController loadViewIfRequired] + 1384
    19  UIKit                               0x01e401ed -[UIViewController view] + 35
    20  UIKit                               0x01cedf94 -[UIWindow addRootViewControllerViewIfPossible] + 69
    21  UIKit                               0x01cee6b1 -[UIWindow _setHidden:forced:] + 304
    22  UIKit                               0x01ceea67 -[UIWindow _orderFrontWithoutMakingKey] + 49
    23  UIKit                               0x01d02118 -[UIWindow makeKeyAndVisible] + 80
    24  UIKit                               0x01c6a6e7 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4190
    25  UIKit                               0x01c71cd6 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1989
    26  UIKit                               0x01c96ee5 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke3218 + 68
    27  UIKit                               0x01c6e966 -[UIApplication workspaceDidEndTransaction:] + 163
    28  FrontBoardServices                  0x04c4dc76 __37-[FBSWorkspace clientEndTransaction:]_block_invoke_2 + 71
    29  FrontBoardServices                  0x04c4d74d __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 54
    30  FrontBoardServices                  0x04c6b173 -[FBSSerialQueue _performNext] + 184
    31  FrontBoardServices                  0x04c6b5aa -[FBSSerialQueue _performNextFromRunLoopSource] + 52
    32  FrontBoardServices                  0x04c6a8a6 FBSSerialQueueRunLoopSourceHandler + 33
    33  CoreFoundation                      0x017fd6ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    34  CoreFoundation                      0x017f338b __CFRunLoopDoSources0 + 523
    35  CoreFoundation                      0x017f27a8 __CFRunLoopRun + 1032
    36  CoreFoundation                      0x017f20e6 CFRunLoopRunSpecific + 470
    37  CoreFoundation                      0x017f1efb CFRunLoopRunInMode + 123
    38  UIKit                               0x01c6e206 -[UIApplication _run] + 540
    39  UIKit                               0x01c73bfa UIApplicationMain + 160
    40  Checking Rest Kit                   0x000af02a main + 138
    41  libdyld.dylib                       0x03911a21 start + 1
    42  ???                                 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

     In Rconnection.m
    - (id)destinationObjectForMappingRepresentation:(id)representation parentRepresentation:(id)parentRepresentation withMapping:(RKMapping *)mapping inRelationship:(RKRelationshipMapping *)relationshipMapping 

    /* Some Code */
    ............
    if (destinationObject == nil)

    NSDictionary *dictionaryRepresentation = [representation isKindOfClass:[NSDictionary class]] ? representation : @ [NSNull null] : representation ;
    RKMappingMetadata *parentMetadata = [RKMappingMetadata new];
    parentMetadata.parentObject = self.destinationObject ?: [NSNull null];
    NSArray *metadata = RKInsertInMetadataList(self.metadataList, parentMetadata, nil);
    RKMappingSourceObject *sourceObject = [[RKMappingSourceObject alloc] initWithObject:dictionaryRepresentation parentObject:parentRepresentation rootObject:self.rootSourceObject metadata:metadata];
    // Crashing Breakpoint below:
    destinationObject = [dataSource mappingOperation:self targetObjectForRepresentation:(NSDictionary *)sourceObject withMapping:concreteMapping inRelationship:relationshipMapping];


   .......
   /* Some code */

#import <Foundation/Foundation.h>
#import <RestKit/RestKit.h>


@interface RJobObject : NSObject

@property (nonatomic) NSString * id;
@property (nonatomic) long long duration;
@property (nonatomic) NSString * title;
@property (nonatomic) NSString * image;
@property (nonatomic) NSString * secret;
@property (nonatomic) NSInteger unreadCount;
@property (nonatomic) NSArray * messages;

+(RKObjectMapping *)mapping;

@end

【问题讨论】:

提供崩溃的详细信息。消息被映射到不同的类类型?猜测这是一个数据源问题,没有创建该类的实例(或者没有响应适当的选择器)。 请包含完整的RJObject头文件(或至少@interface声明) @Wain 添加了堆栈跟踪。你可以看看。 【参考方案1】:

此行不正确:

mappingOperation.dataSource = (id)jobObj;

因为您为操作提供了一个纯数据模型对象作为数据源(并通过强制转换为 id 来告诉编译器喜欢它)。

当操作运行时,它需要创建一些新实例,以便将 JSON dict 中的内容映射到它们中,这是数据源应该做的工作。当操作询问数据源时,您会遇到崩溃,因为您作为数据源提供的对象jobObj 不理解请求。

您需要创建和设置可以处理此要求的适当数据源。

【讨论】:

以上是关于如何使用 RKMappingOperation 将本地 NSDictionary 映射到自定义对象?的主要内容,如果未能解决你的问题,请参考以下文章

在 Avkit 中如何使用这三行代码,以及如何将音乐静音”

如何使用静态库传输资源文件(如何将资源包装在包中)?

如何将 CameraX 与 PreviewView 一起使用?

如何将 groupBy 与 MagicalRecord 一起使用?

如何将 ASTextNode 与 TTTAttributedLabel 一起使用

我们如何将 OCP 与委托一起使用?