首页 > 解决方案 > CompactMapValues 不适用于这个简单的字典

问题描述

我有一个看起来像的模型:

public struct Profile {
  public let bio: String?
  public let company: String
  public let createdDate: Date
  public let department: String
  public let email: String
  public let firstName: String
  public let coverImageURL: URL?
  public let jobTitle: String
  public let lastName: String
  public let location: String?
  public let name: String
  public let profileImageURL: URL?
  public let roles: [String]
  public let isActive: Bool
  public let updatedDate: Date?
  public let userID: String

  public init(
    bio: String?, company: String, createdDate: Date, department: String, email: String, firstName: String, coverImageURL: URL?, jobTitle: String,
    lastName: String, location: String?, name: String, profileImageURL: URL?, roles: [String], isActive: Bool, updatedDate: Date?, userID: String) {
    self.bio = bio
    self.company = company
    self.createdDate = createdDate
    self.department = department
    self.email = email
    self.firstName = firstName
    self.coverImageURL = coverImageURL
    self.jobTitle = jobTitle
    self.lastName = lastName
    self.location = location
    self.name = name
    self.profileImageURL = profileImageURL
    self.roles = roles
    self.isActive = isActive
    self.updatedDate = updatedDate
    self.userID = userID
  }


}

extension Profile: Equatable { }

我正在尝试创建一个将其表示为的元组(model: Profile, json: [String: Any])

使用以下方法 -

  func makeProfile() -> (model: Profile, json: [String: Any]) {

    let updatedDate = Date()
    let updatedDateStr = updatedDate.toString(dateFormat: "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX")
    let createdDate = Date()
    let createdDateStr = createdDate.toString(dateFormat: "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX")

    let coverImageURL = makeURL("https://headerUri.com")
    let profileImageURL = makeURL("https://pictureUri.com")
    let model = Profile(
      bio: "Some Bio",
      company: "Cool Job INC",
      createdDate: createdDate,
      department: "Engineering",
      email: "name@domain.tld",
      firstName: "Anne",
      coverImageURL: coverImageURL,
      jobTitle: "Test Dummy",
      lastName: "Employee",
      location: "London",
      name: "Anne Employee",
      profileImageURL: profileImageURL,
      roles: ["ADMIN"],
      isActive: true,
      updatedDate: updatedDate,
      userID: UUID().uuidString
    )

    let json: [String: Any] = [
      "bio": model.bio,
      "company": model.company,
      "createdDate": createdDateStr,
      "department": model.department,
      "email": model.email,
      "firstName": model.firstName,
      "headerUri": model.coverImageURL?.absoluteString,
      "jobTitle": model.jobTitle,
      "lastName": model.lastName,
      "location": model.location,
      "name": model.name,
      "pictureUri": model.profileImageURL?.absoluteString,
      "roles": model.roles,
      "isActive": model.isActive,
      "updatedDate": updatedDateStr,
      "userId": model.userID
      ].compactMapValues { $0 }

    return (model: model, json: json)
  }
}

extension Date {
  func toString(dateFormat format: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = format
    return dateFormatter.string(from: self)
  }
}

所有可选属性都显示警告Expression implicitly coerced from 'String?' to 'Any'

在此处输入图像描述

我已添加.compactMapValues { $0 }到 dict 但没有效果。

如何清除此警告?

标签: swiftstructswift-optionals

解决方案


您收到一个错误,因为您试图将一个可选值(可能是 nil)隐式强制为Any,这隐藏了该值可能是 nil。

compactMapValues不保证在编译时该值不为零;编译器所知道的是,可选的东西(如String?)现在被视为非可选的Any

避免错误的一种方法是提供默认值而不是可选值:

let json: [String: Any] = [
   "bio": model.bio ?? ""
    // ...
   ]

或者,您可以创建一个字典:[String, Any?]将值分配给,然后使用.compactMapValues,这会给您返回 的非可选值Any

let withOptionals: [String: Any?] = [
   "bio": model.bio,
   // ...
]

let json: [String, Any] = withOptionals.compactMapValues { $0 }

推荐阅读