我有一个jsondata结构,它是从包含以下内容的JSON文件构建的:
{
inputFieldTitle: "Total Cost",
keyboardType: "numberPad"
}在我的代码中,如何使用属性keyboardType初始化UIKeyboardType枚举,以便在TextField上设置键盘类型?
通常我们这样做是为了得到一个numberPad键盘(SwiftUI):
TextField(jsondata.inputFieldTitle) { ... }
.keyboardType(.numberPad)但是在我的场景中,我不能使用.numberPad对keyboardType进行硬编码,我必须使用在jsondata中指定的内容,我如何使用该值在TextField上设置keyboardType?这显然不起作用,因为UIKeyboardType的类型是Int:
TextField(jsondata.inputFieldTitle) { ... }
.keyboardType(UIKeyboardType(rawValue: jsondata.keyboardType))有什么建议吗?谢谢。
发布于 2020-11-24 03:30:20
您可以使UIKeyboardType符合Decodable并实现您自己的自定义解码器方法:
extension UIKeyboardType: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
let rawValue = try container.decode(Int.self)
guard let keyboardType = UIKeyboardType(rawValue: rawValue) else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "invalid UIKeyboardType rawValue: \(rawValue)")
}
self = keyboardType
} catch DecodingError.typeMismatch {
let string = try container.decode(String.self)
guard let keyboardType = UIKeyboardType(string) else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "invalid UIKeyboardType string: \(string)")
}
self = keyboardType
}
}
init?(_ string: String) {
switch string {
case "default": self = .default
case "asciiCapable": self = .asciiCapable
case "numbersAndPunctuation": self = .numbersAndPunctuation
case "URL": self = .URL
case "numberPad": self = .numberPad
case "phonePad": self = .phonePad
case "namePhonePad": self = .namePhonePad
case "emailAddress": self = .emailAddress
case "decimalPad": self = .decimalPad
case "twitter": self = .twitter
case "webSearch": self = .webSearch
case "asciiCapableNumberPad": self = .asciiCapableNumberPad
case "alphabet": self = .alphabet
default: return nil
}
}
}extension UIKeyboardType: Encodable {
public func encode(to encoder: Encoder) throws {
var encoder = encoder.singleValueContainer()
let string: String
switch self {
case .default: string = "default"
case .asciiCapable: string = "asciiCapable"
case .numbersAndPunctuation: string = "numbersAndPunctuation"
case .URL: string = "URL"
case .numberPad: string = "numberPad"
case .phonePad: string = "phonePad"
case .namePhonePad: string = "namePhonePad"
case .emailAddress: string = "emailAddress"
case .decimalPad: string = "decimalPad"
case .twitter: string = "twitter"
case .webSearch: string = "webSearch"
case .asciiCapableNumberPad: string = "asciiCapableNumberPad"
}
try encoder.encode(string)
}
}extension DataProtocol {
var string: String? { String(bytes: self, encoding: .utf8) }
}游乐场测试:
struct Test: Codable {
let inputFieldTitle: String
let keyboardType: UIKeyboardType
}let numberPadJSON = """
{
"inputFieldTitle": "Total Cost",
"keyboardType": "numberPad"
}
"""do {
let test = try JSONDecoder().decode(Test.self, from: Data(numberPadJSON.utf8))
print(test.keyboardType.rawValue) // 4
let encoded = try JSONEncoder().encode(test)
print(encoded.string ?? "") // {"inputFieldTitle":"Total Cost","keyboardType":"numberPad"}
} catch {
print(error)
}发布于 2020-11-24 02:59:57
UIKeyboardType是-a Int,所以您不能使用rawValue,因为您的json值是string。
以下是可能的解决方案
extension UIKeyboardType {
static private let types = ["numberPad": numberPad] // << extend to all supported
init(_ value: String) {
if let result = Self.types[value] {
self = result
} else {
self = .default
}
}
}现在,您可以将其用作
TextField(jsondata.inputFieldTitle) { ... }
.keyboardType(UIKeyboardType(jsondata.keyboardType))
// .keyboardType(UIKeyboardType(jsondata.keyboardType ?? "")) // if optionalhttps://stackoverflow.com/questions/64974560
复制相似问题