在Swift中的CKRecord上定义下标时出现堆栈溢出 [英] Stack overflow when defining subscript on CKRecord in Swift

查看:96
本文介绍了在Swift中的CKRecord上定义下标时出现堆栈溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题询问是否可以对 CKRecord 使用下标在Swift中。虽然我已经知道如何执行发问者想要的操作,但是每次排列都会给我带来堆栈溢出:

This question asks whether one can use subscripting with CKRecord in Swift. While I already knew how to do what the questioner wanted, every permutation of it gives me a stack overflow:

subscript(key: String) -> CKRecordValue? {
    get {
        return objectForKey(key) as CKRecordValue?
    }
    set {
        setObject(newValue, forKey: key)
    }
}

在getter中发生堆栈溢出。 (我从未尝试过setter,所以它也可能在那里发生。)我尝试使用 objectForKey: objectForKeyedSubscript: valueForKey:。都产生相同的结果:堆栈溢出。

The stack overflow occurs in the getter. (I've never tried the setter, so it may occur there, too.) I've tried implementing with objectForKey:, objectForKeyedSubscript:, and valueForKey:. All produce the same result: a stack overflow.

这很奇怪,因为 CKRecord 肯定是用Objective写的-C。为什么要递归调用Swift的下标方法?这个不成立。内特·库克(Nate Cook)在回答提问者时,想知道为什么Swift不会自动桥接 objectForKeyedSubscript:。好吧,也许执行此操作的代码尚未完全完成,但是会导致此问题。我将不得不尝试另一个具有 objectForKeyedSubscript:的类。

This is very strange, since CKRecord is certainly written in Objective-C. Why would it recursively call Swift's subscript method? It makes no sense. Nate Cook, in his answer to the questioner, wonders why Swift doesn't bridge objectForKeyedSubscript: automatically. Well, maybe the code to do that is not fully baked, but is causing this problem. I will have to try it with another class that has objectForKeyedSubscript:.

通常看来, objectForKeyedSubscript:是桥接的。我使用适当的方法在Objective-C中创建了一个类,将其添加到桥接头文件中,索引器在那里并没有问题地被编译。甚至更好,它可以正常工作而不会引起堆栈溢出。

It appears that objectForKeyedSubscript: is ordinarily bridged. I created a class in Objective-C with the appropriate methods, added it to the bridging header, and the indexers were there and compiled without issue. Even better, it worked without a stack overflow.

这意味着 CKRecord 发生了非常不寻常的事情。

This means that something very unusual is going on with CKRecord.

如果在Swift中创建一个继承自 NSObject 并使用 String 作为键在其上实现下标方法,它变为 objectForKeyedSubscript:。 (对于纯Swift类,我怀疑不是这种情况。)您可以通过将Swift类导入Objective-C并验证 objectForKeyedSubscript:来验证这一点。 。

If you create a class in Swift that descends from NSObject and implements the subscript method on it with a String as the key, this becomes objectForKeyedSubscript:. (For "pure Swift" classes, I suspect this is not the case.) You can verify this by importing your Swift class into Objective-C and verifying that objectForKeyedSubscript: is there.

由于 CKRecord 来自 NSObject ,因此实现了下标覆盖默认实现。此外,似乎 objectForKey: valueForKey:最终都被称为 objectForKeyedSubscript:,导致对下标的调用(读为:与相同),导致堆栈溢出。

Since CKRecord descends from NSObject, implementing subscript overrides the default implementation. Further, it seems that objectForKey: and valueForKey: all ultimately called objectForKeyedSubscript:, which results in (read: "is the same as") a call to subscript, which causes the stack overflow.

这可以解释为什么发生堆栈溢出。它仍然不能解释为什么 objectForKeyedSubscript:没有自动桥接的原因,但这也许是因为 setObject:forKeyedSubscript:的定义。类型签名与规范签名的类型签名稍有不同:-(void)setObject:(id< CKRecordValue>)object forKeyedSubscript:(NSString *)key; 。这对Objective-C没有影响,但可能会使桥接代码崩溃。毕竟,Swift是相当新的东西。

That may explain why the stack overflow occurs. It still does not explain why objectForKeyedSubscript: was not automatically bridged, but perhaps it's because the definition of setObject:forKeyedSubscript: has a slightly different type signature from the canonical one: - (void)setObject:(id <CKRecordValue>)object forKeyedSubscript:(NSString *)key;. This makes no difference to Objective-C, but might trip up the "bridging code". Swift is pretty new, after all.

推荐答案

经过一些测试和调试(通过子类)后,我发现对于 CKRecord objectForKey:确实调用了 objectForKeyedSubscript:。另外,在隐式标记为 @objc 的Swift类中实现下标(通过从降级) NSObject )或明确表示下标被实现为 objectForKeyedSubscript:

After some testing and debugging (via a subclass), I discovered that, for CKRecord, objectForKey: does indeed call objectForKeyedSubscript:. Also, implementing subscript in a Swift class that is marked @objc implicitly (by descending from NSObject) or explicitly means that subscript is implemented as objectForKeyedSubscript:.

这意味着在扩展中的 CKRecord 上实现下标实现,这会导致堆栈溢出。

This means that implementing subscript on CKRecord in an extension hides the default implementation, which causes the stack overflow.

这篇关于在Swift中的CKRecord上定义下标时出现堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆