base64EncodedStringWithOptions在SenTest上崩溃

时间:2014-01-27 21:36:10

标签: ios testing

我在一个只在SenTestCase对象内测试时似乎崩溃的函数遇到了问题。

我要做的是从NSData对象获取base64-Encoded String(实际上是一个序列化的JSON字典)。

以下代码中实际发生的是NSJSONSerialization创建一个NSConcreteData对象,然后在[dataFromDictionary base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]上崩溃

返回的崩溃是test failure: -[NSConcreteData base64EncodedStringWithOptions:]: unrecognized selector sent to instance

(in my SenTestCase implementation)
-(NSString *)paramsAsString {    
    NSDictionary *storedParams = @{@"stringKeyTest":@"testValueString", @"dictionaryKeyTest":@{@"testDictKey":@"testDictValue"}, @"numberKeyTest":@1 };
    NSError *error = nil;
    BOOL paramCheck = [NSJSONSerialization isValidJSONObject:storedParams]; 
//paramCheck is true
    NSData *dataFromDictionary = [NSJSONSerialization dataWithJSONObject:storedParams options:0 error:&error]; 
//dataFromDictionary is actually NSConcreteData
    NSString *stringFromData = [dataFromDictionary base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; 
//should stringify NSData, actually crashes

    return stringFromData; //never reached
}

我一直在谷歌上搜索stackOverflowing并且我的测试目标可能缺少依赖项或标头。我只是无法理解那是什么。这些都不是基金会框架功能吗?

目标中也设置了-all-load-ObjC标志,发生了同样的错误。

更新 在写这篇文章时,我找到了这个bug的解决方案。保留这篇帖子给后人,以防我找到了一个不理想的解决方案。

原来,SenTest是一只红鲱鱼。造成问题的实际原因是构建目标(在测试模拟器中为6.1,在我的开发设备上为7.0)实际上无法访问新制作的公共iOS 7的方法。

我在base64EncodedStringWithOptions:的文档中看到了这一点:

Although this method was only introduced publicly for iOS 7, it has existed since iOS 4

由于我计划支持iOS 5及更高版本,我添加了自己的base64编码/解码实现(基于Matt Gallagher's implementation),现在一切都很顺利。

这是向后不兼容的简单情况。一个很好的教训,要记住未来。

2 个答案:

答案 0 :(得分:16)

如您所述,base64EncodedStringWithOptions是iOS 7方法。如果需要,您可以使用第三方base-64库,但Apple已公开了以前的私有方法base64Encoding,以便与旧iOS版本向后兼容。因此,您可以这样做:

NSString string;

if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
    string = [data base64EncodedStringWithOptions:kNilOptions];  // iOS 7+
} else {
    string = [data base64Encoding];                              // pre iOS7
}

并转换回来:

NSData *data;

if ([NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {
    data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions];  // iOS 7+
} else {
    data = [[NSData alloc] initWithBase64Encoding:string];                           // pre iOS7
}

答案 1 :(得分:0)

原来,SenTest是一只红鲱鱼。导致问题的实际原因是构建目标(在测试模拟器中为6.1,在我的开发设备上为7.0)实际上无法访问新制作的公共iOS 7的方法。

我在base64EncodedStringWithOptions ::

的文档中遇到过这个问题
Although this method was only introduced publicly for iOS 7, it has existed since iOS 4

由于我计划支持iOS 5及更高版本,我添加了自己的base64编码/解码实现(基于Matt Gallagher's implementation),现在一切都很好。

这是向后不兼容的简单情况。这是一个值得关注未来的好教训。