【问题标题】:Optional class initializer parameter in class initializer in SwiftSwift 类初始化器中的可选类初始化器参数
【发布时间】:2019-07-11 04:46:19
【问题描述】:

我有一个名为 User 的类 init,而 User 类包含一些参数。现在在 Offer 类中,您可以看到我将 User 类作为参数传递,但我希望将其作为可选参数。有没有办法在你的参数中有一个可选的类?谢谢

struct User {
    let uid: String
    let username: String

    init(uid: String, dictionary: [String: Any]) {
        self.uid = uid
        self.username = dictionary["username"] as? String ?? ""
    }
}

struct Offer {
    let user: User
    let caption: String
    let imageURL: String
    let creationDate: Date

    init(user: User, dictionary: [String: Any]) {
        self.user = user
        self.caption = dictionary["caption"] as? String ?? ""
        self.imageURL = dictionary["image_url"] as? String ?? ""

        let secondsFrom1970 = dictionary["creation_date"] as? Double ?? 0
        self.creationDate = Date(timeIntervalSince1970: secondsFrom1970)
    }
}

【问题讨论】:

  • 是的,属性user和对应的参数都是可选的

标签: swift class struct init


【解决方案1】:

您的代码混淆了两件不同的事情:使用一组成员值初始化对象,以及从字典中提取这些成员。只需编写两个单独的初始化程序:

import Foundation

struct User {
    let uid: String
    let username: String

    /*
    // Due to the absence of an explicit initializer declaration,
    // the compiler will synthesize an implicit member-wise initailizer like this:
    init(uid: String, username: String) {
        self.uid = uid
        self.username = username
    }
    */
}

extension User {
    // Putting this initializer in an extension preserves he member-wise intializer
    init?(fromDict dict: [String: Any]) {
        guard let uid = dict["uid"] as? String,
              let username = dict["username"]  as? String
        else { return nil }

        self.init(uid: uid, username: username)
    }
}

struct Offer {
    let user: User
    let caption: String
    let imageURL: String
    let creationDate: Date

    /*
    // Due to the absence of an explicit initializer declaration,
    // the compiler will synthesize an implicit member-wise initailizer like this:
    init(
        user: User,
        caption: String,
        imageURL: String,
        creationDate: Date
    ) {
        self.user = user
        self.caption = caption
        self.imageURL = imageURL
        self.creationDate = creationDate
    }
    */
}

extension Offer {
    // Putting this initializer in an extension preserves he member-wise intializer
    init?(fromDict dict: [String: Any]) {
        guard let user = dict["user"] as? User,
              let caption = dict["caption"] as? String,
              let imageURL = dict["image_url"] as? String,
              let secondsFrom1970 = dict["creation_date"] as? Double
        else { return nil }

        self.init(
            user: user,
            caption: caption,
            imageURL: imageURL,
            creationDate: Date(timeIntervalSince1970: secondsFrom1970)
        )
    }
}

一些注意事项:

  1. nil 的情况下使用 nil-coalescing 运算符 (??) 提供无意义的默认值是非常糟糕的做法。它隐藏故障并默默地引入数据完整性问题;不要这样做。
  2. String 不是名为 imageURL 的成员的合适类型。使用URL
  3. 如果这些 dicts 来自 JSON,请使用 Codable 协议自动执行所有这些样板代码。
  4. String 对于 ID 来说是一个糟糕的类型,主要是因为与更合适的类型(如 UUIDInt)相比,它真的很慢。在大多数数据库中尤其如此,其中文本比较比 Int/UUID 比较慢。

【讨论】:

  • 谢谢你,你真的知道你在做什么!我真的很感激。
  • 我发现了一个问题。在用户结构中,我必须有一个 uid 参数,对于优惠结构,我必须有用户参数
  • @MutaebAlqahtani 为什么你“必须”拥有这些参数?调用代码是什么样的?
【解决方案2】:

首先这不是class 这是struct,它们都是不同的。

您可以轻松创建如下所示的可选参数。 您还需要将user 属性标记为可选。

struct Offer {
    let user: User?
    let caption: String
    let imageURL: String
    let creationDate: Date

    init(user: User? = nil, dictionary: [String: Any]) {
        self.user = user
        self.caption = dictionary["caption"] as? String ?? ""
        self.imageURL = dictionary["image_url"] as? String ?? ""

        let secondsFrom1970 = dictionary["creation_date"] as? Double ?? 0
        self.creationDate = Date(timeIntervalSince1970: secondsFrom1970)
    }
}

【讨论】:

  • 谢谢,但是我之前尝试过还是有问题。我收到此错误消息(调用中的参数“用户”缺少参数)。我想像这个提议​​(字典:[String:Any])一样高大上。没有用户参数!
  • @MutaebAlqahtani 只需在此处查看可以使用默认参数 init 的编辑
  • @MutaebAlqahtani 为什么你从我的答案中删除了正确的标记?,如果你仍然遇到任何问题,你可以告诉我
  • 我没有删除任何东西。请为我的问题投票
猜你喜欢
  • 2021-01-17
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 2016-04-11
  • 2015-03-04
  • 1970-01-01
  • 2020-08-29
  • 2014-08-21
相关资源
最近更新 更多