我有一个Objective-C应用程序工作得很好和流畅,对Swift更舒服我决定在Swift中为这个应用程序编写单元测试。
Swift中的一些概念对我来说很奇怪,例如,在我的app中需要填写服务器提供的内容列表,在Objective-C中,这看起来(不完全)就像这样:
[self.service requestContentsFrom:0 to:10 response:^(NSArray *result, NSArray *errors) {
ContentModel *firstContent = result[0];
NSLog("Content name: %@ Content date: %@", firstContent.name, firstContent.date);
}];
我这个简单的请求,如果填写结果列表(NSArray),我将收到ContentModel
的列表,因为服务实例实现了一些序列化级别(感谢JSONModel)
要在Swift中对此请求进行简单测试,我做了类似的事情:
func testContentsFromZeroToTen() {
service?.requestContentsFrom(0, 10) { (result, errors) -> Void in
}
}
我的问题是,在Swift中我的result
参数来到[AnyObject]!
并看起来这个数组被正确填充,但其中的类型与Objective-C收到的不一样调用
如果我尝试转换为NSArray
,例如....
let contents = result as NSArray
...然后在控制台中打印的每个内容如下所示:
(AnyObject) content = (instance_type = Builtin.RawPointer = 0x00007fd605213000 -> 0x000000010fa902c8 (void *)0x000000010fa902f0: __NSCFDictionary)
最奇怪的是,如果我打印contents
,我可以看到有关它的更一致的信息:
<__NSCFArray 0x7f95d7608110>(
{
datetime = 1418855742226;
id = 1;
name = "Content 1";
},
{
datetime = 1418855742326;
id = 2;
name = "Content 2";
)
喂!我的模型在那里,但是我输入的模型在哪里,而不是ContentModel
,我看到__NSCFDictionary
我希望得到一个像这样的Swift数组:
let contents = result as [ContentModel]
但是当我尝试上面的代码时,当我在控制台中打印时,我的内容看起来像这样:
([ContentModel]) contents = 2 values {
[0] = <error: use of undeclared identifier 'cocoarr'
error: 1 errors parsing expression
>
[1] = <error: use of undeclared identifier 'cocoarr'
error: 1 errors parsing expression
>
}
所以问题是,如何正确地转换Swift数组以获得类似Objective-C的类型化NSArray?
更新1:添加了ContentModel界面
#import <Foundation/Foundation.h>
#import "JSONModel.h"
#import "UserModel.h"
@interface ContentModel : JSONModel
@property (nonatomic, assign) NSInteger id;
@property (nonatomic, strong) NSDate *datetime;
@property (nonatomic, strong) NSString *text;
@property (nonatomic, strong) UserModel *user;
@end
答案 0 :(得分:1)
首先,NSArray
未在Objective-C中输入。它是一个任意类的数组。这正是[AnyObject]
的内容。 AnyObject
是对任何类的引用。
现在,要将AnyObject
数组的元素作为另一种更具体的类型进行访问,您有两种选择:
一次转换整个数组:
func testContentsFromZeroToTen() {
service?.requestContentsFrom(0, 10) { (result, errors) -> Void in
if let contentModels = result as? [ContentModel] {
for contentModel in contentModels {
}
}
}
}
或者您可以一次转换一个元素:
func testContentsFromZeroToTen() {
service?.requestContentsFrom(0, 10) { (result, errors) -> Void in
for next in result {
if let contentModel = next as? ContentModel {
}
}
}
}
第二个选项允许某些单个元素不是您期望的类型的场景。在第一种情况下,如果一个元素不是ContentModel,您将跳过整个数组。
注意:您也可以在我的示例中执行强制转换而不是可选的转换:
let contentModels = result as [ContentModel]
let contentModel = next as ContentModel
但如果演员失败,这些会让你失败。
最后,当您在Swift中打印出一个对象时,它会打印出一些默认值(通常不是非常有用的信息)。如果要自定义对象打印的内容,可以让自定义类型实现Printable或DebugPrintable协议:
class ContentModel: Printable {
var description: String {
return "Some description"
}
}