Ето един много прост клас (подклас на 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 с моя невинен масив. Също така, как мога да продължавам да използвам NSObject
като основен клас и да имам масиви от CFType
обекти като CGPath
силен>.
Също така бе отбелязано (Благодаря, @user102008!), че не е задължително да е подклас на NSObject
, но свойството просто трябва да бъде декларирано @objc
.
Има някаква документация за целите на използването на @objc
и подкласирането на Objective-C клас в Swift:
Когато дефинирате клас Swift, който наследява от NSObject или друг клас Objective-C, класът автоматично е съвместим с Objective-C.
Въпреки това се опитвам да използвам моя клас Swift от Swift. В документацията не се споменават странични ефекти на различно поведение при подкласиране на клас Objective-C и използването му в Swift. Но документацията също така споменава свързване на Swift масиви към NSArray
:
Когато преминавате от Swift масив към
NSArray
обект, елементите в Swift масива трябва да саAnyObject
съвместими.
И продължава да казва:
Ако елемент в масив Swift не е
AnyObject
съвместим, възниква грешка по време на изпълнение, когато преминете къмNSArray
обект.
Хмммм, CGPath
не е AnyObject
съвместим, но Swift не би трябвало да се опитва да преобразува моя Swift масив в NSArray
.
NSObject
; свойството просто трябва да бъде декларирано@objc
, за да възникне този проблем - person user102008   schedule 30.07.2014CGPath
еNSObject
съвместим по време на изпълнение.(CGPathCreateMutable() as AnyObject) is NSObject
се оценява като true. - person newacct   schedule 05.08.2014If you never import a Swift class in Objective-C code, you don’t need to worry about type compatibility in this case as well.
- person Andrew   schedule 05.08.2014