【问题标题】:RestKit & Cocoapods: Mapping operation failed / did not find any mappable valuesRestKit & Cocoapods:映射操作失败/没有找到任何可映射的值
【发布时间】:2014-05-25 22:17:21
【问题描述】:

使用RKMappingTests 对 RestKit 映射代码执行单元测试时,它们会失败并出现以下异常:

Mapping operation failed: Given nil destination object and unable to instantiate a destination object for mapping.

或者(当目标对象被传递到RKMappingTest时):

Mapping operation did not find any mappable values for the attribute and relationship mappings in the given object representation


RestKit 是通过 Cocoapods 使用以下 Podfile 安装的:

target :MyTarget do
    pod 'RestKit'
end

target :MyTargetTests do
    pod 'RestKit/Testing'
    pod 'RestKit/Search'
end

要测试的 RKMapping 是在常规应用程序包中创建的,并且在使用 lldb 调试器的 po 命令时结果正确。

当生成 RKEntityMapping 的方法被复制粘贴到单元测试类并在那里执行时,一切正常。


注意:

虽然我确实回答了自己的问题,希望它对遇到同样问题的其他人有用,但我鼓励任何能想出更好解决方案的人发布它。

【问题讨论】:

    标签: ios objective-c restkit cocoapods


    【解决方案1】:

    发生这种情况的原因:

    免责声明:
    我不是静态库、链接和相关依赖项方面的专家。如果我对链接或 Cocoapods 的工作方式有任何错误,请纠正我。

    对于这个Podfile,Cocoapods 构建了两个静态库——每个目标一个。

    编译项目后,MyTarget 中的所有代码将链接到 LibPods-MyTarget.a 库,MyTargetTests 中的所有代码将链接到 LibPods-MyTargetTests.a 库。
    它们都包含RestKit/ObjectMapping 组件的副本(因为它是RestKitRestKit/Testing 的依赖项)。

    在应用程序源(MyTarget)中生成RKMapping 时,使用来自LibPods-MyTarget.a 的类实现。
    在单元测试类中使用该映射时,RestKit 实现与其他库链接。

    理论上,两个实现都包含相同的源代码,两个类具有相同的名称、相同的类号,甚至可能甚至底层的objc_class 结构都包含相同的内容。

    当您从测试类调用它的方法时,它将按应有的方式执行(实现来自应用程序库)。 说:根据对象被分配的位置,相同的源代码将从不同的副本加载到不同的内存位置。

    但是,由于 Objective-C 的 Class 结构比底层的 objc_class 结构更高级别,因此它们并不相同。


    含义示例:

    假设我们有一个名为MyObject 的类,其中包含一个具有以下签名的方法:

    + (RKObjectMapping*)generateMapping;
    

    虽然方法本身工作得很好,但这个测试会失败:

    - (void)testClassEquality {
        RKEntityMapping *mappingFromAppBundle = [MyObject generateMapping];
        Class testBundleMappingClass = [RKMapping class];
        
        XCTAssert([mappingFromAppBundle isMemberOfClass:testBundleMappingClass],
                  @"Mapping class from app bundle doesn't match Mapping class from test bundle");
    }
    

    因为:

    [RKMapping class] 来自LibPods-MyTarget.a
    !=
    [RKMapping class] 来自LibPods-MyTargetTests.a


    RestKit 严重依赖 isMemberOfClass:isSubclassOf: 操作来实现其功能。因此这种重复的实现会破坏它。


    解决方案:

    又快又脏:

    不要对两个目标使用两种不同的 Cocoapod 配置。使用简单的 Podfile,例如:

    pod 'RestKit'    
    pod 'RestKit/Testing'
    pod 'RestKit/Search'
    

    然后对两个目标使用相同的库/配置。链接器链接到两个目标的同一个副本。

    dead-code-stripping 应该防止不需要的代码包含在您的最终应用程序中。

    但是:仍然需要在每次构建时对其进行编译,如果您设置了 -ObjC-all_load 链接器标志,则未使用的代码将随您的应用一起提供。

    更脏:

    我强烈建议不要这样做,因为它几乎违背了单元测试的目的。我将其视为另一种解决方法,并将其包括在内以完成:

    将代码的实现复制并粘贴到单元测试类中并从那里使用它。

    建议:

    Cocoapods 首先为每个组件创建一个静态库,然后将它们组合成一个更大的库,用于每个目标、项目或工作区。

    应该可以将小型库直接链接到目标而不使用大联合。这样做,如果没有自动化,就会破坏自动依赖管理,而 Cocoapods 就是为之而构建的。

    如果有人有时间并为此实现脚本或修改 Cocoapods 以添加功能,请告诉我。


    其他解决方案?

    如果我缺少 Cocoapods 已有的功能,或者您知道任何其他解决方案,请发表评论或将其作为另一个答案发布。

    【讨论】:

    • 我遇到了同样的问题,但是当我尝试快速而肮脏的解决方案时,我在 RK 类上收到重复的警告。有什么建议吗?
    • 你找到解决办法了吗?
    • @Tim Bodeit,你是如何继续使用相同的配置的?
    • 通常由pod install自动设置。但要确保:在配置下的信息选项卡中转到您的项目设置 -> 基于配置文件。
    猜你喜欢
    • 2012-11-08
    • 2023-03-29
    • 1970-01-01
    • 2015-11-07
    • 2014-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多