【发布时间】:2018-01-29 01:45:42
【问题描述】:
在尝试使用基本 JSONEncoder 序列化 float3 对象数组时,发现 float3 不符合 Codable 协议,因此无法这样做。
我尝试按照Encoding and Decoding Custom Types 中的建议编写一个基本扩展,如下所示,但是对于 init 中的每个分配行都会呈现错误 'self' used before all stored properties are initialized。我认为这是因为编译器不确定 Float.self 是在 float3 初始化之前定义的,但我不确定如何解决这个问题。
此外,初始化的末尾说Return from initializer without initializing all stored properties,我认为这意味着除了x、y和z之外还有float3属性,但我想知道是否有办法默认/忽略这些,和/或者如何找到完整的属性列表,除了挖掘 simd 中的所有 float3 扩展。
如果您对如何执行此操作有任何想法,我们将不胜感激。谢谢!
import SceneKit
extension float3: Codable {
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
x = try values.decode(Float.self, forKey: .x)
y = try values.decode(Float.self, forKey: .y)
z = try values.decode(Float.self, forKey: .z)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(x, forKey: .x)
try container.encode(y, forKey: .y)
try container.encode(z, forKey: .z)
}
enum CodingKeys: String, CodingKey {
case x
case y
case z
}
}
这是 simd 文件中的(我认为是完整的)float3 定义:
/// A vector of three `Float`. This corresponds to the C and
/// Obj-C type `vector_float3` and the C++ type `simd::float3`.
public struct float3 {
public var x: Float
public var y: Float
public var z: Float
/// Initialize to the zero vector.
public init()
/// Initialize a vector with the specified elements.
public init(_ x: Float, _ y: Float, _ z: Float)
/// Initialize a vector with the specified elements.
public init(x: Float, y: Float, z: Float)
/// Initialize to a vector with all elements equal to `scalar`.
public init(_ scalar: Float)
/// Initialize to a vector with elements taken from `array`.
///
/// - Precondition: `array` must have exactly three elements.
public init(_ array: [Float])
/// Access individual elements of the vector via subscript.
public subscript(index: Int) -> Float
}
extension float3 : Equatable {
/// True iff every element of lhs is equal to the corresponding element of
/// rhs.
public static func ==(lhs: float3, rhs: float3) -> Bool
}
extension float3 : CustomDebugStringConvertible {
/// Debug string representation
public var debugDescription: String { get }
}
extension float3 : ExpressibleByArrayLiteral {
/// Initialize using `arrayLiteral`.
///
/// - Precondition: the array literal must exactly three
/// elements.
public init(arrayLiteral elements: Float...)
}
extension float3 : Collection {
/// The position of the first element in a nonempty collection.
///
/// If the collection is empty, `startIndex` is equal to `endIndex`.
public var startIndex: Int { get }
/// The collection's "past the end" position---that is, the position one
/// greater than the last valid subscript argument.
///
/// When you need a range that includes the last element of a collection, use
/// the half-open range operator (`..<`) with `endIndex`. The `..<` operator
/// creates a range that doesn't include the upper bound, so it's always
/// safe to use with `endIndex`. For example:
///
/// let numbers = [10, 20, 30, 40, 50]
/// if let index = numbers.index(of: 30) {
/// print(numbers[index ..< numbers.endIndex])
/// }
/// // Prints "[30, 40, 50]"
///
/// If the collection is empty, `endIndex` is equal to `startIndex`.
public var endIndex: Int { get }
/// Returns the position immediately after the given index.
///
/// The successor of an index must be well defined. For an index `i` into a
/// collection `c`, calling `c.index(after: i)` returns the same index every
/// time.
///
/// - Parameter i: A valid index of the collection. `i` must be less than
/// `endIndex`.
/// - Returns: The index value immediately after `i`.
public func index(after i: Int) -> Int
}
extension float3 {
/// Vector (elementwise) sum of `lhs` and `rhs`.
public static func +(lhs: float3, rhs: float3) -> float3
/// Vector (elementwise) difference of `lhs` and `rhs`.
public static func -(lhs: float3, rhs: float3) -> float3
/// Negation of `rhs`.
prefix public static func -(rhs: float3) -> float3
/// Elementwise product of `lhs` and `rhs` (A.k.a. the Hadamard or Schur
/// vector product).
public static func *(lhs: float3, rhs: float3) -> float3
/// Scalar-Vector product.
public static func *(lhs: Float, rhs: float3) -> float3
/// Scalar-Vector product.
public static func *(lhs: float3, rhs: Float) -> float3
/// Elementwise quotient of `lhs` and `rhs`.
public static func /(lhs: float3, rhs: float3) -> float3
/// Divide vector by scalar.
public static func /(lhs: float3, rhs: Float) -> float3
/// Add `rhs` to `lhs`.
public static func +=(lhs: inout float3, rhs: float3)
/// Subtract `rhs` from `lhs`.
public static func -=(lhs: inout float3, rhs: float3)
/// Multiply `lhs` by `rhs` (elementwise).
public static func *=(lhs: inout float3, rhs: float3)
/// Divide `lhs` by `rhs` (elementwise).
public static func /=(lhs: inout float3, rhs: float3)
/// Scales `lhs` by `rhs`.
public static func *=(lhs: inout float3, rhs: Float)
/// Scales `lhs` by `1/rhs`.
public static func /=(lhs: inout float3, rhs: Float)
}
【问题讨论】:
-
你的 float3 结构声明在哪里?这些 x、y、z 是您的自定义类型中声明的唯一属性吗?请注意,以大写字母
CamelCase开头的类、结构、枚举和协议的命名是 Swift 命名约定 -
@LeoDabus 我认为 float3 结构一定是 obj-c 的遗留物——这不是我定义的,但似乎是在 simd 文件中定义的。
-
需要导入和框架吗?
-
尝试在
let values ...之前添加self.init() -
天啊...谢谢!我以为我已经尝试过了,但意识到我试图初始化超类(obv. can't on struct)
标签: swift initialization scenekit swift4 codable