RestKit & Cocoapods:映射操作失败/没有找到任何可映射的值
Posted
技术标签:
【中文标题】RestKit & Cocoapods:映射操作失败/没有找到任何可映射的值【英文标题】:RestKit & Cocoapods: Mapping operation failed / did not find any mappable values 【发布时间】:2014-05-25 22:17:21 【问题描述】:使用RKMappingTest
s 对 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 的方法被复制粘贴到单元测试类并在那里执行时,一切正常。
注意:
虽然我确实回答了自己的问题,希望它对遇到同样问题的其他人有用,但我鼓励任何能想出更好解决方案的人发布它。
【问题讨论】:
【参考方案1】:发生这种情况的原因:
免责声明:我不是静态库、链接和相关依赖项方面的专家。如果我对链接或 Cocoapods 的工作方式有任何错误,请纠正我。
对于这个Podfile
,Cocoapods 构建了两个静态库——每个目标一个。
编译项目后,MyTarget
中的所有代码将链接到 LibPods-MyTarget.a
库,MyTargetTests
中的所有代码将链接到 LibPods-MyTargetTests.a
库。
它们都包含RestKit/ObjectMapping
组件的副本(因为它是RestKit
和RestKit/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
自动设置。但要确保:在配置下的信息选项卡中转到您的项目设置 -> 基于配置文件。以上是关于RestKit & Cocoapods:映射操作失败/没有找到任何可映射的值的主要内容,如果未能解决你的问题,请参考以下文章
没有带有 cocoapods 和 swift 的模块“RestKit”
错误:“沙箱与 Podfile.lock 不同步...”在使用 cocoapods 安装 RestKit 后
通过 Cocoapods 安装 RestKit 0.20.0 后基础类型未知
Restkit 0.20.x cocoapods 安装问题 - 编译但找不到 RestKit 的导入