即使满足要求,失败的初始化程序也始终返回nil

时间:2020-01-21 13:25:05

标签: ios swift

如果具有以下代码,则应将[String: any]文档从Firestore转换为结构。

当时我进行调试时,所有条件都已满足,但返回后的值为nil

我尝试将init?更改为常规init,并将else { fatalError() }上的guard更改为 struct Banner { let destinationUrl: URL let imageUrl: URL let endTime: Date let startTime: Date let priority: Int let trackingKeyClicked: String let trackingKeyDismissed: String init?(document: [String: Any]) { guard let destinationUrlString = document["destinationUrl"] as? String, let destinationUrl = URL(string: destinationUrlString), let imageUrlString = document["imageUrl"] as? String, let imageUrl = URL(string: imageUrlString), let priority = document["priority"] as? Int, let trackingKeyClicked = document["trackingKeyClicked"] as? String, let trackingKeyDismissed = document["trackingKeyDismissed"] as? String, let startTime = document["startTime"] as? Date, let endTime = document["endTime"] as? Date else { return nil } self.destinationUrl = destinationUrl self.imageUrl = imageUrl self.priority = priority self.trackingKeyClicked = trackingKeyClicked self.trackingKeyDismissed = trackingKeyDismissed self.endTime = endTime self.startTime = startTime } } // using it like this let bannerStructs = querySnapshot.documents.map { Banner(document: $0.data()) } 。如果数据有效,它将起作用并返回有效的结构。

失败的初始化程序在做什么?

这不起作用(即使有有效数据也总是返回nil):

 struct Banner {
        let destinationUrl: URL
        // ...
        let endTime: Date

        init(document: [String: Any]) {
            guard
                let destinationUrlString = document["destinationUrl"] as? String,
                let destinationUrl = URL(string: destinationUrlString),
                // ....
                let endTime = document["endTime"] as? Date
                else { fatalError() }
            self.destinationUrl = destinationUrl
            // ...
            self.endTime = endTime
        }
    }

这适用于有效数据(但在错误数据上崩溃而不是返回nil):

useQuery

3 个答案:

答案 0 :(得分:1)

如果没有一个guard let条件得到满足,它将失败并最终触发fatalError或返回nil,这取决于您使用的实现方式。 请正确调试哪些数据没有正确解析/广播。

我设置了一个很好的示例来说明您可能希望它如何工作,而另一个不好的例子则是为了让您知道用这种格式无法预期的attribute可以使{{ 1}}返回initialiser

nil

这是打印出来的内容:

import Foundation

struct Banner {
    let destinationUrl: URL
    let imageUrl: URL
    let endTime: Date
    let startTime: Date
    let priority: Int
    let trackingKeyClicked: String
    let trackingKeyDismissed: String

    init?(document: [String: Any]) {
        guard
            let destinationUrlString = document["destinationUrl"] as? String,
            let destinationUrl = URL(string: destinationUrlString),
            let imageUrlString = document["imageUrl"] as? String,
            let imageUrl = URL(string: imageUrlString),
            let priority = document["priority"] as? Int,
            let trackingKeyClicked = document["trackingKeyClicked"] as? String,
            let trackingKeyDismissed = document["trackingKeyDismissed"] as? String,
            let startTime = document["startTime"] as? Date,
            let endTime = document["endTime"] as? Date
            else { return nil }
        self.destinationUrl = destinationUrl
        self.imageUrl = imageUrl
        self.priority = priority
        self.trackingKeyClicked = trackingKeyClicked
        self.trackingKeyDismissed = trackingKeyDismissed
        self.endTime = endTime
        self.startTime = startTime
    }
}

// using it like this
let goodData:[String:Any] = [
    "destinationUrl": "http://destination--url",
    "imageUrl": "http://image-url",
    "priority": 17,
    "trackingKeyClicked": "Tracking Key Clicked",
    "trackingKeyDismissed": "Tracking Key Dismissed",
    "startTime": Date(),
    "endTime": Date()
    ]
let goodBannerStructs = Banner(document: goodData)

let badData:[String:Any] = [
    "destinationUrl": "http://destination--url",
    "imageUrl": "http://image-url",
    "priority": 17,
    "trackingKeyClicked": "Tracking Key Clicked",
    "trackingKeyDismissed": "Tracking Key Dismissed",
    "startTime": "17 December",
    "endTime": Date()
    ]
let badBannerStructs = Banner(document: badData)

print("Good banner: \(goodBannerStructs)")
print("Bad banner: \(badBannerStructs)")

您可以在http://online.swiftplayground.run/

上尝试以下代码

可能是Good banner: Optional(Banner(destinationUrl: http://destination--url, imageUrl: http://image-url, endTime: 2020-01-21 17:45:27 +0000, startTime: 2020-01-21 17:45:27 +0000, priority: 17, trackingKeyClicked: "Tracking Key Clicked", trackingKeyDismissed: "Tracking Key Dismissed")) Bad banner: nil 的字典键可能与查询中的内容不正确,可能是document可能不是Int或日期可能是String。您必须对其进行调试。

答案 1 :(得分:1)

如果可失败的初始化程序返回nil且正常的初始化程序由于数据损坏而崩溃,那么这将我引向可失败的初始化程序中的guard语句,导致该失败而返回nil。在guard语句内的return nil行上放置一个断点,看看是否被击中。

答案 2 :(得分:0)

这不起作用(即使有有效数据也总是返回nil)

由于您的guard始终失败,因此数据似乎不正确。我猜想startDateendDate转换为Date并不是那么容易。您能发表一个json数据的例子吗?

如果这是原因,here就是描述如何使用DateFormatter从字符串创建日期的人。如果您的日期遵循ISO8601,则可以使用苹果ISO8601DateFormatter来完成。