在本文中,您将会了解到关于Swift结构:为单个属性处理多种类型的新资讯,同时我们还将为您解释swift构造方法的相关在本文中,我们将带你探索Swift结构:为单个属性处理多种类型的奥秘,分析swif
在本文中,您将会了解到关于Swift结构:为单个属性处理多种类型的新资讯,同时我们还将为您解释swift构造方法的相关在本文中,我们将带你探索Swift结构:为单个属性处理多种类型的奥秘,分析swift构造方法的特点,并给出一些关于10.4 Swift结构体中的mutating方法、12.6 Swift结构体的构造方法、5.3 Swift的结构(struct)类型及其下标(subscript) [Swift原创教程]、8.1 Swift结构体定义的实用技巧。
本文目录一览:- Swift结构:为单个属性处理多种类型(swift构造方法)
- 10.4 Swift结构体中的mutating方法
- 12.6 Swift结构体的构造方法
- 5.3 Swift的结构(struct)类型及其下标(subscript) [Swift原创教程]
- 8.1 Swift结构体定义
Swift结构:为单个属性处理多种类型(swift构造方法)
我正在使用Swift 4并尝试解析一些JSON数据,这些数据显然在某些情况下对于同一键可能具有不同的类型值,例如:
{ "type": 0.0}
和
{ "type": "12.44591406"}
我实际上坚持定义我的名字,struct
因为我不知道如何处理这种情况,因为
struct ItemRaw: Codable { let parentType: String enum CodingKeys: String, CodingKey { case parentType = "type" }}
抛出"Expected to decode String but found a number instead."
,自然,
struct ItemRaw: Codable { let parentType: Float enum CodingKeys: String, CodingKey { case parentType = "type" }}
相应地抛出"Expected to decode Float but found a string/data instead."
。
定义我时如何处理这种(和类似的)情况struct
?
答案1
小编典典尝试对Reddit列表JSON响应上的“已编辑”字段进行解码/编码时遇到了相同的问题。我创建了一个结构,该结构表示给定键可能存在的动态类型。键可以是布尔值或整数。
{ "edited": false }{ "edited": 123456 }
如果只需要能够解码,则只需实现init(from :)。如果您需要同时使用两种方法,则需要实现encode(to :)函数。
struct Edited: Codable { let isEdited: Bool let editedTime: Int // Where we determine what type the value is init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() // Check for a boolean do { isEdited = try container.decode(Bool.self) editedTime = 0 } catch { // Check for an integer editedTime = try container.decode(Int.self) isEdited = true } } // We need to go back to a dynamic type, so based on the data we have stored, encode to the proper type func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try isEdited ? container.encode(editedTime) : container.encode(false) }}
在我的Codable类中,然后使用我的结构。
struct Listing: Codable { let edited: Edited}
编辑:针对您的方案的更具体的解决方案
我建议在解码时使用CodingKey协议和一个枚举来存储所有属性。当您创建符合Codable的内容时,编译器将为您创建一个私有枚举CodingKeys。这使您可以根据JSON
Object属性键决定要做什么。
仅举例来说,这就是我正在解码的JSON:
{"type": "1.234"}{"type": 1.234}
如果您只想将double值从字符串转换为Double,则只需解码字符串,然后从中创建一个double。(这是Itai
Ferber所做的,然后您还必须使用trycoder.decode(type:forKey :)对所有属性进行解码)
struct JSONObjectCasted: Codable { let type: Double? init(from decoder: Decoder) throws { // Decode all fields and store them let container = try decoder.container(keyedBy: CodingKeys.self) // The compiler creates coding keys for each property, so as long as the keys are the same as the property names, we don''t need to define our own enum. // First check for a Double do { type = try container.decode(Double.self, forKey: .type) } catch { // The check for a String and then cast it, this will throw if decoding fails if let typeValue = Double(try container.decode(String.self, forKey: .type)) { type = typeValue } else { // You may want to throw here if you don''t want to default the value(in the case that it you can''t have an optional). type = nil } } // Perform other decoding for other properties. }}
如果需要将类型和值一起存储,则可以使用符合Codable的枚举而不是struct。然后,您可以仅使用具有JSONObjectCustomEnum的“
type”属性的switch语句,并根据大小写执行操作。
struct JSONObjectCustomEnum: Codable { let type: DynamicJSONProperty}// Where I can represent all the types that the JSON property can be. enum DynamicJSONProperty: Codable { case double(Double) case string(String) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() // Decode the double do { let doubleVal = try container.decode(Double.self) self = .double(doubleVal) } catch DecodingError.typeMismatch { // Decode the string let stringVal = try container.decode(String.self) self = .string(stringVal) } } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .double(let value): try container.encode(value) case .string(let value): try container.encode(value) } }}
10.4 Swift结构体中的mutating方法
/**
结构体中的mutating方法
值类型(结构体或者枚举)默认方法是不可以修改属性的,也不可以修改self本身
如果要修改需要做特殊处理,函数前加上 mutating。
当然在类 (class)里面当然是可以修改属性的。
*/
class MyPerson {
var name: String = ""
var age: Int = 0
func set(name: String,age: Int) -> Void {
self.name = name
self.age = age
}
func show() -> Void {
print("name=\(name),age=\(age)")
}
}
var m0 = MyPerson.init()
m0.set(name: "zhangsan",age: 10)
m0.show()
struct MyPerson1 {
var name: String = ""
var age: Int = 0
mutating func set(name: String,age: Int) -> Void {
/**
结构体枚举等值类型的中,这里在普通的实例方法中不允许修改属性
如果一定要修改,在func前面加上 mutating;
如果 MyPerson1 是class 就没有必要加mutating
*/
self.name = name
self.age = age
}
func show() -> Void {
print("name=\(name),age=\(age)")
}
}
// 这个不可以修改
// let m11 = MyPerson1.init()
// m11.set(name: 1,age: 1)
var m10 = MyPerson1.init()
m10.set(name: "zhangsan",age: 10)
m10.show()
// 枚举里面
enum LightSwitch {
case OFF,LOW,HIGH
// 在枚举中确实可以有成员方法或者实例方法
// 加上 mutating,才可以修改 self
mutating func next() {
switch self {
case .OFF:
self = .LOW
case .LOW:
self = .HIGH
case .HIGH:
self = .OFF
default:
self = .OFF
}
}
}
var light = LightSwitch.OFF
// 调用之后,此时此刻 light == .LOW
light.next()
12.6 Swift结构体的构造方法
/**
结构体的构造方法
结构体的构造方法和类的构造方法还是有区别的
*/
struct Rect {
var width: Double
var height: Double
// 针对结构体,系统会提供一个结构体成员逐一构造器,所以上面没有初始化值。在类里面没有这个
// init(width: Double,height: Double) {
// self.width = width
// self.height = height
// }
// 如果自定义相应的构造方法,那么系统提供的结构体逐一成员构造器失效
// init() {
// }
}
var r0 = Rect.init(width: 2,height: 1)
// print(r0.width)
// print(r0.height)
5.3 Swift的结构(struct)类型及其下标(subscript) [Swift原创教程]
原文:http://coolketang.com/staticCoding/5a9925ac128fe1189bdbd578.html
1. struct结构体是构建代码常用的一种通用灵活的构造体。通过为结构体定义属性和方法,可以扩展结构体的功能。本节课为你演示结构体的使用。
2. 使用struct关键词可以定义一个结构体,结构体的名称通常使用首字母大写的形式。和枚举相同的是,结构体的内容也是放在一对大括号之内。
3. 给结构体定义一个字符串类型的属性,并设置它的默认值为空字符串。
4. 定义一个整型类型的属性,并设置它的默认值为0。
5. 给结构体定义一个方法,用来在控制台输出名称属性的值。
6. 接着实例化一个结构体对象,并设置它的两个属性的值。
7. 调用结构体对象的方法,并查看第11行右侧输出的结果。
8. 当将一个结构体对象赋值给一个变量或常量时,采用的是复制的方式。所以此时animal和animal2两个变量具有不同的内存地址。
9. 你可以尝试修改第二个结构体对象的名称。
10. 然后输出两个结构体对象,并点击底部的显示调试区图标,打开控制台。
11. 从控制台的日志输出可以看出,两个结构体对象具有不同的名称属性。再次点击底部的显示调试区图标,隐藏控制台。
12. 继续编写代码,演示结构体的下标特性。
13. 首先创建一个新的结构体。
14. 给结构体添加一个整型的属性。
15. 然后使用下标关键词,给结构体添加一个下标操作,该下标用来返回当前属性的值的指定倍数。使用下标可以作为访问集合、列表或序列成员元素的快捷方式。
16. 接着初始化一个结构体对象,并设置其属性的值为5。
17. 最后对结构体对象使用下标操作,从右侧的实时反馈区可以看出,最终的结果是当前属性值的两倍。
8.1 Swift结构体定义
/**
8.1-结构体定义.mp4
与 C 中的结构体比较
C 语言中的结构体,不同类型的数据,或者相同类型的数据构成的集合。
不一样的就是Swift语言中的结构体可以拥有方法,甚至是我们后面要讲的构造方法、析构方法
*/
/**
C 语言中我们这样子写结构体
struct Rect {
Double width;
Double height;
}
*/
// swift 中
struct Rect {
var width: Double
var height: Double
}
今天关于Swift结构:为单个属性处理多种类型和swift构造方法的讲解已经结束,谢谢您的阅读,如果想了解更多关于10.4 Swift结构体中的mutating方法、12.6 Swift结构体的构造方法、5.3 Swift的结构(struct)类型及其下标(subscript) [Swift原创教程]、8.1 Swift结构体定义的相关知识,请在本站搜索。
本文标签: