我有一个 Objective-C 应用程序运行良好且流畅,为了更熟悉 Swift,我决定用 Swift 为这个应用程序编写单元测试。
Swift 中的一些概念对我来说看起来很奇怪,例如,在我的应用程序中需要填写服务器提供的内容列表,在 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接口(interface)
#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
最佳答案
首先,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 协议(protocol):
class ContentModel: Printable {
var description: String {
return "Some description"
}
}
关于ios - 将自定义对象的 NSArray 转换为 Swift 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27609828/