如何以`\uuu SwiftValue为伪装获得swift结构的实际类型`

如何以`\uuu SwiftValue为伪装获得swift结构的实际类型`,swift,value-type,any,encoder-decoder,Swift,Value Type,Any,Encoder Decoder,我正在使用YapDatabase对我的Swift值类型进行编码/解码。解码后,类型信息似乎丢失,即类型(of:element)返回\uuu SwiftValue,而不是,例如保留 但是,如果我在调试器中调用po元素,类型信息似乎仍然保留: (lldb) po element SecureTruckParking.Reservation(reservationId: 12625, accessInformations: [SecureTruckParking.AccessInformation(

我正在使用YapDatabase对我的Swift值类型进行编码/解码。解码后,类型信息似乎丢失,即
类型(of:element)
返回
\uuu SwiftValue
,而不是,例如
保留

但是,如果我在调试器中调用
po元素
,类型信息似乎仍然保留:

(lldb) po element 
SecureTruckParking.Reservation(reservationId: 12625, accessInformations: [SecureTruckParking.AccessInformation(accessInformationId: 12706, accessTypeId: 1, accessTypeKey: Optional("1"), accessTypeTenantKey: Optional("ROOT"), encodedValue: "XXX", displayedValue: "XXX"), SecureTruckParking.AccessInformation(accessInformationId: 12707, accessTypeId: 51, accessTypeKey: Optional("51"), accessTypeTenantKey: Optional("ROOT"), encodedValue: "918296", displayedValue: "918296")], customerId: 3156, areaId: 552, productId: 1004, state: "PENDING", startTime: 2020-09-10 08:23:00 +0000, endTime: 2020-09-11 08:23:00 +0000, earliestEntryTime: 2020-09-10 08:23:00 +0000, latestExitTime: 2020-09-11 08:23:00 +0000, totalAmount: 2750.0, currency: "€", netPrice: 2311.0, taxPrice: 439.0, invoiceItems: [SecureTruckParking.InvoiceItem(amount: 1, itemText: "Parkplatzreservierung, 10.09.2020 10:23 - 11.09.2020 10:23 \nREWE Logistikzentrum Neu-Isenburg -> REWE Logistikzentrum Neu-Isenburg", netPrice: 2311.0, taxPrice: 439.0, taxRate: 19.0)], productAttributes: [SecureTruckParking.Attribute(key: "early_bird_count", value: Optional("1"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "early_bird_count", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "DETAILS", value: nil, definitionId: nil), SecureTruckParking.Attribute(key: "INFO_DETAILS", value: nil, definitionId: nil), SecureTruckParking.Attribute(key: "early_bird", value: Optional("false"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "early_bird", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "manualBackofficeCancellationConfirmation", value: Optional("false"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "manualBackofficeCancellationConfirmation", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "manualBackofficeCancellationConfirmationThreshold", value: Optional("1"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "manualBackofficeCancellationConfirmationThreshold", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "product_icon", value: nil, definitionId: Optional(SecureTruckParking.DefinitionId(key: "product_icon", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "product_image", value: nil, definitionId: Optional(SecureTruckParking.DefinitionId(key: "product_image", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "product_tariff_group", value: nil, definitionId: Optional(SecureTruckParking.DefinitionId(key: "product_tariff_group", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "upgrading", value: Optional("false"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "upgrading", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "upgrading_dates_fixed", value: Optional("false"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "upgrading_dates_fixed", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "upgrading_immediate", value: Optional("false"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "upgrading_immediate", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "upgrading_mail", value: Optional("false"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "upgrading_mail", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "upgrading_price_surcharge", value: Optional("false"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "upgrading_price_surcharge", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "early_bird_duration", value: Optional("1440"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "early_bird_duration", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "recurring_max_trips", value: Optional("1"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "recurring_max_trips", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "upgrading_mail_max_lead_time", value: nil, definitionId: Optional(SecureTruckParking.DefinitionId(key: "upgrading_mail_max_lead_time", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "upgrading_mail_min_lead_time", value: nil, definitionId: Optional(SecureTruckParking.DefinitionId(key: "upgrading_mail_min_lead_time", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "bstp_product_type", value: Optional("Reservation"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "bstp_product_type", tenant: "ROOT")))], areaAttributes: [SecureTruckParking.Attribute(key: "product_icon", value: nil, definitionId: Optional(SecureTruckParking.DefinitionId(key: "product_icon", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "product_image", value: nil, definitionId: Optional(SecureTruckParking.DefinitionId(key: "product_image", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "Parking_Area_UST", value: Optional("22222222222222"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "Parking_Area_UST", tenant: "MAN_BOSCH"))), SecureTruckParking.Attribute(key: "ipaw_id", value: Optional("4651"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "ipaw_id", tenant: "ROOT"))), SecureTruckParking.Attribute(key: "bstp_area_type", value: Optional("PROFESSIONAL"), definitionId: Optional(SecureTruckParking.DefinitionId(key: "bstp_area_type", tenant: "ROOT")))])

这是什么?
\uuu SwiftValue
,有没有办法得到实际的类型(除了解析
字符串(描述:element
)的可怕方法之外)?

首先,您看到的是
\uuu SwiftValue
,因为
结构已用
包装为AnyObject
强制转换。您可以自己轻松验证这一点:

struct TestStruct {}
let ourStruct = TestStruct()
let structSwiftValue = ourStruct as AnyObject
print(type(of: ourStruct))
print(type(of: structSwiftValue))
产出:

TestStruct
__SwiftValue
ModuleName.TestStruct
NSObject
TestStruct
__SwiftValue
关于这一主题的良好讨论:

现在谈谈你问题的实质,不幸的是,我认为目前还没有方便的公共API允许你从
\uuuu SwiftValue
中提取原始元数据
Type

尽管如此,这个话题还是太有趣了,不能不冒险进入私人API领域进行教育

让我们从SwiftValue本身开始

obj-c提供了有前景的API:

// Private methods for debugging purposes.

- (const Metadata *)_swiftTypeMetadata {
  return getSwiftValueTypeMetadata(self);
}
- (id /* NSString */)_swiftTypeName {
  TypeNamePair typeName
    = swift_getTypeName(getSwiftValueTypeMetadata(self), true);
  id str = swift_stdlib_NSStringFromUTF8(typeName.data, typeName.length);
  return [str autorelease];
}
- (const OpaqueValue *)_swiftValue {
  return getValueFromSwiftValue(self).second;
}
让我们从一件相当简单的事情开始:

print(structSwiftValue.value(forKey: "_swiftTypeName")!)
产出:

TestStruct
__SwiftValue
ModuleName.TestStruct
NSObject
TestStruct
__SwiftValue
只是一个
字符串
类型,但对初学者来说还不错。下一个有希望探索的候选者似乎是:

- (const Metadata *)_swiftTypeMetadata()
我们可以这样称呼它(可以找到有关Swift中调用选择器的这种特殊方式的详细信息)

现在的挑战是如何以
类型(of:)
的方式使用
元数据*
(即桥接到Swift后的
不透明指针

我找到了一种方法,尽管这是一种非常粗糙的方法。
我们从某个虚拟对象或结构的元数据
Type
变量开始(其实并不重要)。总体思路是最终我们希望用上一阶段得到的元数据指针替换元数据指针。我注意到
Type(of:)
产生一个指向元数据的指针,因此存在额外的间接寻址级别,我们必须考虑:

var placeholderTypeVar: Any.Type = type(of: NSObject())
print(placeholderTypeVar)
withUnsafeMutablePointer(to: &placeholderTypeVar) {
    let unsafePtr = UnsafeMutablePointer<OpaquePointer>.allocate(capacity: 1)
    unsafePtr.pointee = metadataPtr
    $0.assign(from: UnsafePointer<Any.Type>.init(OpaquePointer(unsafePtr)), count: 1)
}
print(placeholderTypeVar)
print(type(of: structSwiftValue))
中间的一个是答案。而且它与
类型(of:ourStruct)
的结果相同,一直到内存级别(内部生成的
元数据*
等价物是非常相同的地址!)

更多了解Swift中非常有趣的元数据主题:

您是否尝试打印
元素.self
?@s1lentwarior是的,此打印与
采购订单元素
相同,并且
采购订单类型(属于:any.self)
再次导致
\uu SwiftValue