使用迅速NSObject的子类的CoreFoundation对象时运行时错误 [英] Runtime error when using CoreFoundation objects in a swift NSObject subclass
问题描述
下面是一个非常简单的类(子类 NSObject的
),保持 CGPath
对象的列表,并附加有一个 CGPath
在数组初始化
:
进口基金会
MyClass类:NSObject的{ VAR名单= [CGPath](); 在里面() {
list.append(CGPathCreateMutable());
}
}
当尝试使用这个类:
VAR实例= MyClass的();
的println(instance.list.count); //加入这一行后,运行时错误
产生一个丑陋的崩溃:
游乐场执行失败:错误:执行被中断,原因是:EXC_BAD_INSTRUCTION(code = EXC_I386_INVOP,分code =为0x0)。
这个过程一直留在它被中断的点,用主题返回-x前pression评价前返回的状态。
*线#1:TID = 0x1251d1,0x00000001064ce069 libswiftFoundation.dylib`partial为Swift._ContiguousArrayBuffer申请代理(_ asCocoaArray< A>(Swift._ContiguousArrayBuffer< A>) - GT;() - GT; Swift._CocoaArray)(关闭#1)重整的后缀392+ 121,队列='com.apple.main线程,停止的原因= EXC_BAD_INSTRUCTION(code = EXC_I386_INVOP,分code =为0x0)
*帧#0:0x00000001064ce069 libswiftFoundation.dylib`partial申请转发器Swift._ContiguousArrayBuffer(_ asCocoaArray< A>(Swift._ContiguousArrayBuffer< A>) - GT;() - GT; Swift._CocoaArray)(关闭#1)与重整的后缀392+ 121
帧#1:0x00000001064ce0d8 libswiftFoundation.dylib`partial申请转发器reabstraction thunk的助手< T_0_0>从@callee_owned(@In T_0_0) - GT; (@owned Swift.AnyObject)到@callee_owned(@In T_0_0) - GT; (@out Swift.AnyObject)与重整的后缀395+ 56
帧#2:0x00000001057bf29a libswift_stdlib_core.dylib`Swift.MapSequenceGenerator.next< A:Swift.Generator,B>(@ INOUT Swift.MapSequenceGenerator< A,B>)() - GT; Swift.Optional< B> + 554
帧#3:Swift.Generator.next&LT 0x00000001057bf49a libswift_stdlib_core.dylib`protocol见证; A:Swift.Generator>(@ INOUT Swift.Generator.Self)() - GT; Swift.Optional< Swift.Generator.Self.Element>在一致性Swift.MapSequenceGenerator:Swift.Generator + 58
帧#4:0x00000001064d8e97 libswiftFoundation.dylib`Swift._copyCollectionToNativeArrayBuffer< A:协议< Swift._Collection,Swift._Sequence_>>(A) - GT; Swift._ContiguousArrayBuffer< A.GeneratorType.Element> + 1511
帧#5:0x00000001064f1951为Swift.Sequence libswiftFoundation.dylib`protocol见证〜方式> @infix< A:Swift.Sequence>(Swift.Sequence.Self.Type)(Swift.Sequence.Self,(Swift._CopyToNativeArrayBuffer,())) - > Swift._ContiguousArrayBuffer< Swift.Sequence.Self.GeneratorType.Element>在一致性Swift.LazyRandomAccessCollection:Swift.Sequence + 449
帧#6:0x00000001064daf7b libswiftFoundation.dylib`Swift.ContiguousArray.map< A>(Swift.ContiguousArray< A>)< B>((A) - > B) - > Swift.ContiguousArray< B> + 1339
帧#7:0x00000001064da9cb libswiftFoundation.dylib`Swift._ContiguousArrayBuffer._asCocoaArray< A>(Swift._ContiguousArrayBuffer< A>)() - GT; Swift._CocoaArray + 475
帧#8:0x00000001064ced3e libswiftFoundation.dylib`Swift._ArrayBuffer._asCocoaArray< A>(Swift._ArrayBuffer< A>)() - GT; Swift._CocoaArray + 78
帧#9:0x000000010649f583 libswiftFoundation.dylib`Foundation._convertArrayToNSArray< A>(Swift.Array< A>) - GT; ObjectiveC.NSArray + 35
帧#10:0x000000011163b40e
框#9抓住了我的眼球: libswiftFoundation.dylib \\`Foundation._convertArrayToNSArray
。为什么会迅速试图我漂亮,快乐,斯威夫特数组转换成的NSArray
?
只有在一个阵列使用 CFType
对象时出现此问题。我可以在阵列中使用 NSObject的
子就好了(例 [UIBezierPath]
)
问题可以很容易地通过不继承 NSObject的
是固定的,但是我想知道究竟迅速在做我的清白阵列。 同时,我怎么可以仍然可以使用 NSObject的
作为基类,有数组 CFType
对象,如 CGPath
也有人指出的(感谢@ user102008!)的,它并没有成为 NSObject的
的子类,但物业只是要声明 @objc
。
有<一个href=\"https://developer.apple.com/library/$p$prelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_36\"相对=nofollow>一些文档使用的目的 @objc
和斯威夫特继承的Objective-C类的:
当你定义从NSObject的或其他任何继承的类斯威夫特
Objective-C类,这个类是自动兼容
Objective-C的。
块引用>不过,我从内斯威夫特尝试使用雨燕我的班。有没有副作用继承的Objective-C类和斯威夫特在使用它时,不同的行为的文件中提及。但是,文件中还提到桥接斯威夫特阵列
的NSArray
:
当您从斯威夫特阵列的
的NSArray
对象桥,元素
雨燕数组中必须AnyObject
兼容。
块引用>和接着说:
如果在斯威夫特数组中的元素不是
AnyObject
兼容,当你缩小到的NSArray
对象。
块引用>嗯,
CGPath
不是AnyObject
兼容,但斯威夫特的不应该的试图我斯威夫特数组转换成的NSArray
。解决方案
嗯,CGPath不AnyObject兼容,但斯威夫特不应该尝试我的雨燕数组转换成一个NSArray。
块引用>它必须。你说你希望它是ObjC兼容,ObjC不能直接处理斯威夫特阵列。因此它有将其转换为一个NSArray
简短的回答是,这是工作完全一样记录。由于这是iOS的,该解决方案,但是,是微不足道的。只需切换到UIBezierPath(这是AnyObject兼容),而不是CGPath。
Here's a very simple class (subclass of
NSObject
) that keeps a list ofCGPath
objects and appends oneCGPath
to the array oninit
:import Foundation class MyClass: NSObject { var list = [CGPath](); init() { list.append(CGPathCreateMutable()); } }
When trying to use this class:
var instance = MyClass(); println(instance.list.count); // runtime error after adding this line
Yields an ugly crash:
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
Frame #9 caught my eye:
libswiftFoundation.dylib\`Foundation._convertArrayToNSArray
. Why would swift be trying to convert my nice, happy, Swift array into anNSArray
?This issue only occurs when using
CFType
objects in an array. I can useNSObject
subclasses in the array just fine (Ex.[UIBezierPath]
)The issue can easily be fixed by not subclassing
NSObject
, however I want to know what exactly swift is doing to my innocent array. Also, how I can still useNSObject
as the base class and have arrays ofCFType
objects such asCGPath
.It was also pointed out (Thanks, @user102008!) that it doesn't have to be a subclass of
NSObject
, but the property just has to be declared@objc
.There is some documentation on purpose of using
@objc
and subclassing an Objective-C class in Swift:When you define a Swift class that inherits from NSObject or any other Objective-C class, the class is automatically compatible with Objective-C.
However, I am trying the use my Swift class from within Swift. There is no mention of side effects in the documentation of different behavior when subclassing an Objective-C class and using it within Swift. But the documentation also mentions bridging Swift arrays to
NSArray
:When you bridge from a Swift array to an
NSArray
object, the elements in the Swift array must beAnyObject
compatible.And goes on to say:
If an element in a Swift array is not
AnyObject
compatible, a runtime error occurs when you bridge to anNSArray
object.Hmmmm,
CGPath
isn'tAnyObject
compatible, but Swift shouldn't be trying to convert my Swift array into anNSArray
.解决方案Hmmmm, CGPath isn't AnyObject compatible, but Swift shouldn't be trying to convert my Swift array into an NSArray.
It has to. You said you want it to be ObjC compatible, and ObjC can't handle Swift arrays directly. So it has to convert it to an NSArray.
The short answer is that this is working exactly as documented. Since this is iOS, the solution, however, is trivial. Just switch to UIBezierPath (which is AnyObject compatible) rather than CGPath.
这篇关于使用迅速NSObject的子类的CoreFoundation对象时运行时错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!