I'm debugging my program to check if the value of a property is correctly set, I put a breakpoint in this function:
我正在调试我的程序来检查属性的值是否正确设置,我在这个函数中放了一个断点:
func showContent(data: Any) -> UIView {
// breakpoint here
var contentView = UIView()
if let image = data as? UIImage {
let imageView = UIImageView()
imageView.image = image
contentView = imageView
}
if let text = data as? String {
let label = UILabel()
label.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
label.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
label.text = text
contentView = label
}
return contentView
}
the value passed to this function is from a view controller:
传递给此函数的值来自视图控制器:
override func viewDidLoad() {
calcGroupFamiliarity()
flashCardView.linkedMemory = Memory(masteryLevel: 1, algorithm: Algorithm.algorithm1.chooseAlgorithm(), forgetRatio: 0, lastStudyTime: Date(), front: #imageLiteral(resourceName: "Ideas-Blue"), back: #imageLiteral(resourceName: "Ideas-Yellow"))
}
as you can see, both the front
and the back
are images, however, in the debugger they both appeared as some payload_data
, while the data type of other values such as masteryLevel
, algorithm
are correct:
正如您所看到的,前面和后面都是图像,但是,在调试器中它们都显示为一些payload_data,而其他值的数据类型(如masteryLevel,algorithm)是正确的:
Can somebody explain what that means? And what should I do to pass the normal image data instead?
有人能解释一下这意味着什么吗?我应该怎样做才能传递正常的图像数据呢?
Update:
更新:
This is Memory
class:
这是Memory类:
class Memory: NSObject, NSCoding {
var masteryLevel: Int
var algorithm: [Int: Double]
var forgetRatio: Int
var lastStudyTime: Date
var strength: Double = 0
var front: Any
var back: Any
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask)[0]
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("Memory")
init(masteryLevel: Int, algorithm: [Int: Double], forgetRatio: Int, lastStudyTime: Date, front: Any, back: Any){
self.masteryLevel = masteryLevel
self.algorithm = algorithm
self.forgetRatio = forgetRatio
self.lastStudyTime = lastStudyTime
self.front = front
self.back = back
}
...
}
2 个解决方案
#1
2
This is a detail of how Swift implements the Any
type. Given that Swift can't know beforehand what you are putting into e.g. front
, it needs to store a pointer to that object (in payload_data_0
) as well as a pointer to metadata about the stored object's type (in instance_type
). As far as I know, payload_data_1
and payload_data_2
are there as an optimization so that Swift can store up to 24-byte large structs in place rather than having to put them in a wrapper object that needs to be stored in a separate heap location.
这是Swift如何实现Any类型的细节。鉴于斯威夫特事先无法知道你在做什么,例如在前面,它需要存储指向该对象的指针(在payload_data_0中)以及指向存储对象类型(在instance_type中)的元数据的指针。据我所知,payload_data_1和payload_data_2作为优化存在,以便Swift可以存储多达24字节的大型结构,而不必将它们放在需要存储在单独堆位置的包装器对象中。
So, to answer your question: This is neither a bug in Swift, nor an error on your side. Your data gets stored and accessed in the right way. If you would prefer to inspect front
more easily while debugging, try
所以,回答你的问题:这既不是斯威夫特的错误,也不是你身边的错误。您的数据以正确的方式存储和访问。如果您希望在调试时更容易检查前端,请尝试
(lldb) po front
in the debugger. Alternatively, change front
's type to e.g. UIImage?
. If that is not possible, you could declare a protocol
在调试器中。或者,将前面的类型改为例如UIImage的?如果不可能,您可以声明协议
protocol MemoryStoreable: class { }
and extend every type that needs to be stored in those fields like so:
并扩展需要存储在这些字段中的每个类型,如下所示:
extension UIImage: MemoryStoreable { }
and declare the variable as
并将变量声明为
var front: MemoryStoreable?
Note that MemoryStoreable
is restricted to classes, as otherwise a protocol witness would need to be stored (which is again implemented similarly to the Any
field you observed).
请注意,MemoryStoreable仅限于类,否则需要存储协议见证(再次以与您观察到的Any字段类似的方式实现)。
Another alternative would be, if you know you'll store e.g. only images and strings in front
, to use an enum:
另一种选择是,如果你知道你会存储,例如只使用前面的图像和字符串,使用枚举:
enum MemoryStoreable {
case `string`(String)
case image(UIImage)
}
var front: MemoryStoreable?
That will still require at least 25 bytes of storage in your object (possibly 32 due to memory alignment constraints), though, as that's the size of the String
struct.
这仍然需要对象中至少25个字节的存储空间(由于内存对齐约束,可能需要32个字节),因为这是String结构的大小。
For more details, see e.g. https://mikeash.com/pyblog/friday-qa-2014-08-01-exploring-swift-memory-layout-part-ii.html.
有关详细信息,请参阅https://mikeash.com/pyblog/friday-qa-2014-08-01-exploring-swift-memory-layout-part-ii.html。
#2
0
Base on @MrMage's awesome answer.
基于@MrMage的精彩答案。
@MrMage gave 2 suggestions on approaching this problem, it took some effort for me to grasp them, for what I wanted to achieve in the program, it's the perfect scenario for me to go protocol-oriented-programming.
@MrMage提出了2个关于解决这个问题的建议,我花了一些力气去掌握它们,因为我想在程序中实现它,这是我进行面向协议编程的完美场景。
Here's a really easy to understand tutorial that help me a lot: Introduction to Protocol Oriented Programming in Swift
这是一个非常容易理解的教程,它对我有很大帮助:Swift中面向协议编程的简介
Hopefully this can be helpful to you :)
希望这对你有所帮助:)
#1
2
This is a detail of how Swift implements the Any
type. Given that Swift can't know beforehand what you are putting into e.g. front
, it needs to store a pointer to that object (in payload_data_0
) as well as a pointer to metadata about the stored object's type (in instance_type
). As far as I know, payload_data_1
and payload_data_2
are there as an optimization so that Swift can store up to 24-byte large structs in place rather than having to put them in a wrapper object that needs to be stored in a separate heap location.
这是Swift如何实现Any类型的细节。鉴于斯威夫特事先无法知道你在做什么,例如在前面,它需要存储指向该对象的指针(在payload_data_0中)以及指向存储对象类型(在instance_type中)的元数据的指针。据我所知,payload_data_1和payload_data_2作为优化存在,以便Swift可以存储多达24字节的大型结构,而不必将它们放在需要存储在单独堆位置的包装器对象中。
So, to answer your question: This is neither a bug in Swift, nor an error on your side. Your data gets stored and accessed in the right way. If you would prefer to inspect front
more easily while debugging, try
所以,回答你的问题:这既不是斯威夫特的错误,也不是你身边的错误。您的数据以正确的方式存储和访问。如果您希望在调试时更容易检查前端,请尝试
(lldb) po front
in the debugger. Alternatively, change front
's type to e.g. UIImage?
. If that is not possible, you could declare a protocol
在调试器中。或者,将前面的类型改为例如UIImage的?如果不可能,您可以声明协议
protocol MemoryStoreable: class { }
and extend every type that needs to be stored in those fields like so:
并扩展需要存储在这些字段中的每个类型,如下所示:
extension UIImage: MemoryStoreable { }
and declare the variable as
并将变量声明为
var front: MemoryStoreable?
Note that MemoryStoreable
is restricted to classes, as otherwise a protocol witness would need to be stored (which is again implemented similarly to the Any
field you observed).
请注意,MemoryStoreable仅限于类,否则需要存储协议见证(再次以与您观察到的Any字段类似的方式实现)。
Another alternative would be, if you know you'll store e.g. only images and strings in front
, to use an enum:
另一种选择是,如果你知道你会存储,例如只使用前面的图像和字符串,使用枚举:
enum MemoryStoreable {
case `string`(String)
case image(UIImage)
}
var front: MemoryStoreable?
That will still require at least 25 bytes of storage in your object (possibly 32 due to memory alignment constraints), though, as that's the size of the String
struct.
这仍然需要对象中至少25个字节的存储空间(由于内存对齐约束,可能需要32个字节),因为这是String结构的大小。
For more details, see e.g. https://mikeash.com/pyblog/friday-qa-2014-08-01-exploring-swift-memory-layout-part-ii.html.
有关详细信息,请参阅https://mikeash.com/pyblog/friday-qa-2014-08-01-exploring-swift-memory-layout-part-ii.html。
#2
0
Base on @MrMage's awesome answer.
基于@MrMage的精彩答案。
@MrMage gave 2 suggestions on approaching this problem, it took some effort for me to grasp them, for what I wanted to achieve in the program, it's the perfect scenario for me to go protocol-oriented-programming.
@MrMage提出了2个关于解决这个问题的建议,我花了一些力气去掌握它们,因为我想在程序中实现它,这是我进行面向协议编程的完美场景。
Here's a really easy to understand tutorial that help me a lot: Introduction to Protocol Oriented Programming in Swift
这是一个非常容易理解的教程,它对我有很大帮助:Swift中面向协议编程的简介
Hopefully this can be helpful to you :)
希望这对你有所帮助:)