在swift NSObject子类中使用CoreFoundation对象时出现运行时错误

时间:2014-07-28 14:29:51

标签: ios arrays swift nsobject

这是一个非常简单的类(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 } 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

5 个答案:

答案 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的地方(据我所知)。希望这有帮助。 :)