ios - 将自定义对象的 NSArray 转换为 Swift 数组

标签 ios objective-c arrays swift

我有一个 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/

相关文章:

ios - 无操作连接选项

c - 为什么数组的大小和指向第一个元素的指针不同?

html - 如何隐藏 "-"破折号之前的所有文本?

iphone - performSelectorOnMainThread 嵌入在 didUpdateToLocation

iphone - UIScrollView 内的 MKMapView 不会随滑动而移动

ios - 是否可以使用 Google plus API 获取电话号码

ios - 在 BTLE 后台通知触发后拍照

ios - 无法访问 iOS 静态库中资源包文件中的 Storyboard

ios - View中的TableView,如何让它透明

javascript - 将数组字符串元素的长度设置为 JavaScript 中 for 循环中的变量