这是一个非常简单的类(NSObject
的子类),它保留CGPath
个对象的列表,并在CGPath
上的数组中附加一个init
:
import Foundation
class MyClass: NSObject {
var list = [CGPath]();
init() {
list.append(CGPathCreateMutable());
}
}
尝试使用此课程时:
var instance = MyClass();
println(instance.list.count); // runtime error after adding this line
产生丑陋的崩溃:
Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1: tid = 0x1251d1, 0x00000001064ce069 libswiftFoundation.dylib`partial apply forwarder for Swift._ContiguousArrayBuffer.(_asCocoaArray <A>(Swift._ContiguousArrayBuffer<A>) -> () -> Swift._CocoaArray).(closure #1) with unmangled suffix "392" + 121, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
* frame #0: 0x00000001064ce069 libswiftFoundation.dylib`partial apply forwarder for Swift._ContiguousArrayBuffer.(_asCocoaArray <A>(Swift._ContiguousArrayBuffer<A>) -> () -> Swift._CocoaArray).(closure #1) with unmangled suffix "392" + 121
frame #1: 0x00000001064ce0d8 libswiftFoundation.dylib`partial apply forwarder for reabstraction thunk helper <T_0_0> from @callee_owned (@in T_0_0) -> (@owned Swift.AnyObject) to @callee_owned (@in T_0_0) -> (@out Swift.AnyObject) with unmangled suffix "395" + 56
frame #2: 0x00000001057bf29a libswift_stdlib_core.dylib`Swift.MapSequenceGenerator.next <A : Swift.Generator, B>(@inout Swift.MapSequenceGenerator<A, B>)() -> Swift.Optional<B> + 554
frame #3: 0x00000001057bf49a libswift_stdlib_core.dylib`protocol witness for Swift.Generator.next <A : Swift.Generator>(@inout Swift.Generator.Self)() -> Swift.Optional<Swift.Generator.Self.Element> in conformance Swift.MapSequenceGenerator : Swift.Generator + 58
frame #4: 0x00000001064d8e97 libswiftFoundation.dylib`Swift._copyCollectionToNativeArrayBuffer <A : protocol<Swift._Collection, Swift._Sequence_>>(A) -> Swift._ContiguousArrayBuffer<A.GeneratorType.Element> + 1511
frame #5: 0x00000001064f1951 libswiftFoundation.dylib`protocol witness for Swift.Sequence.~> @infix <A : Swift.Sequence>(Swift.Sequence.Self.Type)(Swift.Sequence.Self, (Swift._CopyToNativeArrayBuffer, ())) -> Swift._ContiguousArrayBuffer<Swift.Sequence.Self.GeneratorType.Element> in conformance Swift.LazyRandomAccessCollection : Swift.Sequence + 449
frame #6: 0x00000001064daf7b libswiftFoundation.dylib`Swift.ContiguousArray.map <A>(Swift.ContiguousArray<A>)<B>((A) -> B) -> Swift.ContiguousArray<B> + 1339
frame #7: 0x00000001064da9cb libswiftFoundation.dylib`Swift._ContiguousArrayBuffer._asCocoaArray <A>(Swift._ContiguousArrayBuffer<A>)() -> Swift._CocoaArray + 475
frame #8: 0x00000001064ced3e libswiftFoundation.dylib`Swift._ArrayBuffer._asCocoaArray <A>(Swift._ArrayBuffer<A>)() -> Swift._CocoaArray + 78
frame #9: 0x000000010649f583 libswiftFoundation.dylib`Foundation._convertArrayToNSArray <A>(Swift.Array<A>) -> ObjectiveC.NSArray + 35
frame #10: 0x000000011163b40e
第9帧引起了我的注意:libswiftFoundation.dylib\`Foundation._convertArrayToNSArray
。为什么swift会尝试将我漂亮,快乐的Swift数组转换为NSArray
?
仅在数组中使用CFType
个对象时才会出现此问题。我可以很好地使用数组中的NSObject
子类(例如[UIBezierPath]
)
通过不继承NSObject
可以很容易地解决这个问题,但我想知道swift正在对我的无辜数组做什么。 另外,我如何still use NSObject
作为基类,并拥有CFType
1>} CGPath
对象的数组。
还指出(谢谢,@ user102008!)它不必是NSObject
的子类,但是必须声明属性{{1 }}
有some documentation目的使用@objc
并在Swift中继承Objective-C类:
定义从NSObject或任何其他继承的Swift类 Objective-C类,类自动兼容 目标C
但是,我正在尝试从Swift中使用我的Swift类。在子类化Objective-C类并在Swift中使用它时,没有提及不同行为的文档中的副作用。但文档还提到将Swift数组桥接到@objc
:
当您从Swift数组桥接到
NSArray
对象时,元素 在Swift数组中必须兼容NSArray
。
继续说:
如果Swift数组中的元素不兼容
AnyObject
,则在桥接到AnyObject
对象时会发生运行时错误。
嗯,NSArray
不兼容CGPath
,但Swift 不应尝试将我的Swift数组转换为AnyObject
。
答案 0 :(得分:3)
嗯,CGPath并不是AnyObject兼容的,但是Swift不应该试图将我的Swift数组转换为NSArray。
必须。你说你希望它与ObjC兼容,而且ObjC不能直接处理Swift数组。所以它必须将其转换为NSArray。
简短的回答是,这完全符合记录。由于这是iOS,因此解决方案是微不足道的。只需切换到UIBezierPath(与AnyObject兼容)而不是CGPath。
答案 1 :(得分:1)
Swift中与Objective-C兼容的所有对象都使用完整的Objective-C运行时。这意味着当您创建一个继承自NSObject的类型(或定义为Objective-C兼容)时,其方法和属性使用Messaging而不是在编译时链接到您的方法。
要接收消息,所有纯粹的Swift对象(如阵列)必须转换为Objective-C对应部分。无论您当前是否在Objective-C中使用该对象,都会发生这种情况,因为无论如何,它都使用消息传递。
因此,如果您创建一个继承自NSObject的类,则必须假设所有属性都可以转换为Objective-C对应项。正如您在问题中所述,您可以使用UIBezierPath
代替CGPath
来实现这一目标。
答案 2 :(得分:0)
从“使用Swift与Cocoa和Objective-C”
当你在Objective-C代码中使用Swift类或协议时, importer用导入的API替换所有类型的Swift数组 NSArray的。
因此,根据此,不应将数组转换为NSArray。同样,我也认为你应该提交错误报告。
与此同时,你可以使用相应的Cocoa-Class或将你的CGPath包装在一个额外的对象中。
答案 3 :(得分:0)
import UIKit
class MyClass: NSObject {
var list = [CGPath]();
override init() {
list.append(CGPathCreateMutable());
}
}
var instance = MyClass()
print(instance.list.count) // 1
答案 4 :(得分:-2)
可能你没有导入Foundaion,这是NSObject的地方:
import Foundation
这是包含NSObject的地方(据我所知)。希望这有帮助。 :)