实例方法“驱动器”要求类型“ NotificationItem”和“ [NotificationItem]”等效

时间:2019-11-01 04:56:23

标签: swift rx-swift

我创建了一个称为通知项目的类,并从模型类RTVNotification中解析数据

导入基金会 导入RTVModel

公共类NotificationItem:NSObject {

class Foo {
  constructor (private foo = 1, public bar = 2) {}
}

}

扩展NotificationItem {     静态函数实例化(带有通知:RTVNotification)-> NotificationItem? {

public var id: String
public var title: String
public var comment: String
public var publishStartDateString: String

init(id: String,
     title: String,
     comment: String,
     publishStartDateString: String) {
    self.id = id
    self.title = title
    self.comment = comment
    self.publishStartDateString = publishStartDateString

    super.init()
}

}

ViewModel

公共类SettingsViewModel:ViewModel {

    return NotificationItem(
        id: notification.id,
        title: notification.title,
        comment: notification.comment,
        publishStartDateString: notification.publishStartDateString)

}

-----> .map {NotificationItem.instantiate(with:$ 0)}

var item = [NotificationItem]()

public var fetchedNotifications: Driver<NotificationItem> = .empty()

public var apiErrorEvents: Driver<RTVAPIError> = .empty()

public var notificationCount: Driver<Int> = .empty()

public func bindNotificationEvents(with trigger: Driver<Void>) {

    let webService: Driver<RTVInformationListWebService> = trigger
        .map { RTVInformationListParameters() }
        .webService()

    let result = webService.request()
    apiErrorEvents = Driver.merge(apiErrorEvents, result.error())
    notificationCount = result.success().map {$0.informationList.maxCount }
    fetchedNotifications =
         result.success()
        .map {$0.informationList.notifications}

}

收到一条错误消息,提示无法将类型“ [RTVNotification]”的值转换为预期的参数类型“ RTVNotification” 我该怎么办才能解决这个问题。

2 个答案:

答案 0 :(得分:2)

map()函数的目的是迭代输入数组的元素,并将变换函数应用于这些元素中的每个元素。转换后的元素将添加到map()返回的新输出数组中。重要的是要了解输出数组的长度与输入数组的长度相同。

例如:

let inputArray = ["red", "white", "blue"]
let outputArray = inputArray.map { $0.count } // outputArray is [3, 5, 4]

在您的代码中,您正在调用:

result.success().map { $0.informationList.notifications }

我一点都不了解RxSwift,所以在这里我将进行疯狂的猜测。

首先,我不完全知道result.success()返回什么,但是您可以在其上调用map()的事实意味着result.success()返回一个数组(这很奇怪,但是好吧,我们会去的。)

第二,我们知道result.success()返回的数组包含具有informationList属性的元素,而informationList属性具有名为notifications的属性。我的猜测是notifications是复数,表示notifications属性类型是一个数组,可能是[RTVNotification]

所以这段代码:

result.success().map { $0.informationList.notifications }

success()数组转换为新数组。根据我的假设notifications的类型为[RTVNotification],并进一步假设success()数组仅包含一个元素,我期望得到的结果

result.success().map { $0.informationList.notifications }

成为[[RTVNotification]]类型的数组,即具有一个元素的数组,其中该元素是RTVNotification s的数组。

然后,您将[[RTVNotification]]数组输入另一个map()函数中:

.map { NotificationItem.instantiate(with: $0) }

从该答案的开头回想起map()遍历数组的元素。由于此映射的输入数组为[[RTVNotification]],因此其元素将为[RTVNotification]类型。这就是您通话中的$0-[RTVNotification]。但是instantiate(with:)函数采用RTVNotification,而不是RTVNotification的数组,因此会出现错误:

  

无法将类型“ [RTVNotification]”的值转换为预期的参数类型“ RTVNotification”

那你怎么做才能解决?

我可能会做这样的事情(您必须根据使用情况对其进行调整):

guard let successResponse = webService.request().success().first else {
    print("no success response received")
    return nil // basically report up an error here if not successful
}

// get the list of notifications, this will be type [RTVNotification]
let notifications = successResponse.informationList.notifications

// Now you can create an array of `[NotificationItem]` like you want:
let notificationItems = notifications.map { NotificationItem.instantiate(with: $0) }

// do something with notificationItems...

上面的警告是,如果您需要遍历success()数组中的每个元素,则可以这样做:

let successResponses = webService.result().success()

// successNotifications is of type [[RTVNotification]]
let successNotifications = successResponses.map { $0.informationList.notifications }

// successItems will be of type [[NotificationItem]]
let successItems = successNotifications.map { notifications in
    notifications.map { NotificationItem.instantiate(with: $0) }
}

换句话说,在最后一种情况下,您将获得一个包含NotificationItem数组的数组。

答案 1 :(得分:2)

您的问题在这里: fetchedNotifications: Driver<NotificationItem>应该是fetchedNotifications: Driver<[NotificationItem]>,并且行.map {NotificationItem.instantiate(with: $0)}需要另一张地图您正在处理Observable<Array<RTVNotification>>。您在容器类型中有一个容器类型,因此在地图中需要一个地图:

.map { $0.map { NotificationItem.instantiate(with: $0) } }

如果类型不匹配,则需要更改类型。

代码的其他问题...

  • 驱动程序,可观察变量,主题和中继不应使用var进行定义,它们应始终为let。在调用绑定之前预订属性的对象将连接到.empty()可观察对象,并且永远不会获得任何值。毕竟,这是功能反应式编程。

  • 您的NotificationItem类型应该是struct,或者它的所有属性都应该是let。

请务必阅读并理解@par对这个问题的回答。他写了一个非常好的解释,浪费知识转移将是可耻的。