Voici une classe très simple (sous-classe de Lorsque vous essayez d'utiliser cette classe: p> donne un crash laid: p> NsObject code>) qui conserve une liste des objets code> cgpath code> et ajoute un
cgpath code> au tableau sur init code>:
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
5 Réponses :
C'est probablement le fait que vous n'avez pas importé de baseaion, qui est où nsObject est: C'est là que NsObject est contenu (autant que je sache). J'espère que cela a aidé. :) p> p>
Non. Cela n'a pas aidé. Je l'ai ajouté à mon exemple de question. Quoi qu'il en soit, un "Je ne sais pas où la classe X" est une erreur serait probablement une erreur de compilateur plutôt que d'une erreur d'exécution que je connais.
Désolé à ce sujet alors. Je ne suis pas aussi expérimenté d'un programmeur, alors je pourrais probablement faire des erreurs. : /
Vous avez tort: développeur .apple.com / Bibliothèque / Mac / Documentation / Cocoa / Reference / ...
Si elle a prouvé que la réponse ne résout pas le problème, elle devrait être supprimée.
hmmmm, cgpath n'est pas compatible Néhobject, mais Swift ne devrait pas essayer de convertir mon tableau SWIFT en Nsarray. P> blockQuote>
Il doit. Vous avez dit que vous voulez que ce soit compatible avec Objc et que l'OBJC ne puisse pas gérer directement des tableaux SWIFT. Donc, il doit le convertir en Nsarray. P>
La réponse courte est que cela fonctionne exactement comme documenté. Comme il s'agit de iOS, la solution, cependant, est triviale. Il suffit de passer à UIBZierPath (qui est compatible AnyObject) plutôt que CGPATH. P>
Il va donc (essayer de) le convertir en nsarray code> même lorsque je ne l'utilise pas dans l'objectif-c? Je viens d'appeler
println (myClass (). List.compt); code> à Swift, qui ne semble pas être nécessaire de convertir ...
Vous avez dit que vous vouliez qu'il soit compatible avec l'Objc. Cela prend cette décision au moment de la compilation. Sinon, il faudrait effectuer une conversion éventuellement très coûteuse (qui pourrait échouer) au moment de l'exécution chaque fois que vous l'avez demandé. Si vous voulez vraiment quelque chose comme ça, créez une propriété calculée objc qui convertit pour vous.
La clé ici est de réaliser que Mettre à @ objc à l'avant (ou sous-classement de NsObject) dit "Je veux que vous le stocke de manière compatible avec l'OBJC et que je promets que je n'utiliserai aucune fonctionnalité qui rompre cela."
Je pourrais vous recommander d'ouvrir un radar, cependant. Vous auriez idéalement dû avoir une erreur de compilation à l'annexe () code>.
Je ne suis pas convaincu que ça le stocke comme nsarray code> tel qu'il semble le convertir à
nsarray code> au moment de l'exécution, comme suggéré par
image # 9 code> de la trace de la pile.
Je n'ai pas dit que c'était le stocker comme un Nsarray. J'ai dit qu'il le stockait d'une manière compatible avec l'OBJC, qui ajoute certaines restrictions.
Il utilise toujours un arraybuffer sous les couvertures. Mais dans le cadre 7, vous voyez où il faut qu'il soit compatible avec un "réseau de cacao" puisque vous avez demandé cela dans la définition de type.
Ce qui est plus important, c'est que cela s'écrase à Swift est une bénédiction. La pire réponse serait de travailler à Swift puis de se briser à l'OBJC (puisque vous vouliez évidemment que cela fonctionne à Objc, ou vous n'auriez pas dit cela de cette façon). Vous voulez des choses qui vont échouer de manière fiable. Vous ne voudriez pas que Swift soit «faire de son mieux» et parfois réussir et parfois échouer.
J'ai fait un peu plus de test, et l'erreur ne se produit pas sur l'initialisation d'une instance code> MyClass code>, mais uniquement lorsque j'essaie d'accéder à instance.list code>. Donc, cela suggérerait-il que cela va stocker le tableau, mais une fois que j'essaie d'y accéder, il la convertit à
Nsarray code>?
Qui correspond à ce que vous voyez dans le journal des crash. Il serait préférable que cela n'ait pas échoué plus tôt (à la compilation idéale), et c'est ce que vous pourriez ouvrir un radar. Mais tout cela correspond au comportement attendu de la DOCS IMO. Ne mettez pas de choses non-objc-Safe dans un Var ABJC-ACCESSIBLE. (L'autre radar est que CGPathref devrait être convertible maintenant qu'il est annoté avec cf_implicit_bridgiding_enabled, mais c'est un problème différent.)
Pourquoi cgpath code> pas "
anyobject code> compatible"?
Presque certainement parce que ce n'est pas un NsObject code>. C'est un
cftype code>. Étant donné que cela a été vérifié pour la gestion de la mémoire, j'espère qu'ils pourraient le pondérer à Swift proprement.
@ROBNAPIER: CFTYPE CODE> S est
NsObject code> S au moment de l'exécution.
@Robnapier Core Foundation Objets sont AnyObject CODE> Compatible. Par exemple. Vous avez toujours été en mesure de mettre des types CF dans un
Nsarray code> dans Objective-C en les jetant à
ID code>.
[myarray addObject: (id) mycgcolor] code>
Est-ce une définition documentée de anyobject code>? J'accepte que devrait i> une définition de
anyobject code>, mais je ne sais pas qu'il est actuellement est i> à Swift.
J'aimerais
de "en utilisant Swift avec cacao et objectif-c" p>
Lorsque vous utilisez une classe SWIFT ou un protocole dans le code de l'objectif-C, le L'importateur remplace toutes les matrices SWIFT de tout type d'API importé avec Nsarray. P> blockQuote>
Donc, selon cela, le tableau ne doit pas être converti en Nsarray. Comme cela fait, je pense aussi que vous devriez déposer un rapport de bogue. P>
Entre-temps, vous pouvez utiliser la classe de cacao correspondante ou envelopper votre CGPATH dans un objet supplémentaire. P>
Je ne vois pas comment vous pouvez raisonner que le tableau SWIFT ne doit pas être converti sur cette pièce de documentation. J'utilise ma classe Swift dans un autre code SWIFT.
C'est ce que je veux dire. Cela ne devrait certainement pas être converti. Dans le compilateur Swift, il reste plusieurs bugs. Je suppose que c'est l'un d'entre eux.
Ce texte ne contrainte pas ce qui va se passer lorsque le code SWIFT appelle à un autre code SWIFT, uniquement lorsque l'objectif-C code appelle le code SWIFT.
Tous les objets de Swift compatibles avec Objective-C, utilisez le temps d'exécution complet de l'objectif-C. Cela signifie que lorsque vous établissez un type qui hérite de NsObject (ou est défini comme compatible Objective-C), ses méthodes et ses propriétés utilisent Messagerie au lieu de la liaison au moment de la compilation à votre méthode. P>
Pour recevoir un message, tous les objets purement rapides, comme votre matrice, doivent être convertis en contre-partie de l'objectif-C. Cela se produit indépendamment de si vous utilisez actuellement l'objet dans l'objectif-c car peu importe ce qu'il utilise la messagerie. P>
Par conséquent, si vous faites une classe qui hérite de NsObject, vous devez supposer que toutes les propriétés peuvent être converties en homologues de l'objectif-C. Comme vous l'avez dit dans votre question, vous pouvez y parvenir en utilisant uibezierpath code> au lieu de
cgpath code>. P>
Dans le compilateur Beta 4, vous pouvez éliminer le crash en déclarant la propriété comme final code>, qui indique à Swift, pas d'utiliser la messagerie pour accéder à la propriété. Inversement, le compilateur bêta 5 n'utilise plus la messagerie pour accéder aux propriétés, de sorte qu'il réussit - sauf si vous déclarez la propriété comme
dynamique code>, qui déclenche à nouveau le crash.
import UIKit class MyClass: NSObject { var list = [CGPath](); override init() { list.append(CGPathCreateMutable()); } } var instance = MyClass() print(instance.list.count) // 1
Ooh, a-t-ils réparé ??
Au fait: la classe n'a même pas à la sous-classe
nsobject code>; La propriété doit juste être déclarée
@OBJC code> pour ce problème à se produire
@ user102008 belle prise!
"CGPATH n'est pas compatible de NELObject" Qu'est-ce qui vous fait dire ça? Cela me semble compatible.
@newacct Je suppose que c'est vraiment que cgpath n'est pas compatible NsObject, ce qui signifie qu'il ne peut pas être dans un NSARRAY.
@Santatisslaus: En réalité,
cgpath code> est
nsobject code> compatible au moment de l'exécution.
(CGPathCreatemutable () Comme AnyObject) est NsObject code> est évalué à true.
Mise à jour: Ceci a été corrigé dans Xcode 6 Beta 5
@Newacct Je vais vérifier à nouveau une fois que j'obtiens la dernière version bêta.
On dirait qu'ils ont changé quelque chose:
Si vous n'importez jamais une classe SWIFT dans le code de l'objectif-C, vous n'avez pas besoin de vous inquiéter de la compatibilité de type dans ce cas. Code>