6
votes

Erreur d'exécution lorsque vous utilisez des objets de base de fondation dans une sous-classe Swift NsObject

Voici une classe très simple (sous-classe de NsObject code>) qui conserve une liste des objets code> cgpath code> et ajoute un cgpath code> au tableau sur init code>: xxx pré>

Lorsque vous essayez d'utiliser cette classe: p> xxx pré>

donne un crash laid: p>

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


8 commentaires

Au fait: la classe n'a même pas à la sous-classe nsobject ; La propriété doit juste être déclarée @OBJC 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 est nsobject compatible au moment de l'exécution. (CGPathCreatemutable () Comme AnyObject) est NsObject 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.


5 Réponses :


-2
votes

C'est probablement le fait que vous n'avez pas importé de baseaion, qui est où nsObject est: xxx

C'est là que NsObject est contenu (autant que je sache). J'espère que cela a aidé. :)


4 commentaires

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.



3
votes

hmmmm, cgpath n'est pas compatible Néhobject, mais Swift ne devrait pas essayer de convertir mon tableau SWIFT en Nsarray.

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.

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.


16 commentaires

Il va donc (essayer de) le convertir en nsarray même lorsque je ne l'utilise pas dans l'objectif-c? Je viens d'appeler println (myClass (). List.compt); à 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 () .


Je ne suis pas convaincu que ça le stocke comme nsarray tel qu'il semble le convertir à nsarray au moment de l'exécution, comme suggéré par image # 9 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 MyClass , mais uniquement lorsque j'essaie d'accéder à instance.list . 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 ?


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 pas " anyobject compatible"?


Presque certainement parce que ce n'est pas un NsObject . C'est un cftype . É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 S est NsObject S au moment de l'exécution.


@Robnapier Core Foundation Objets sont AnyObject Compatible. Par exemple. Vous avez toujours été en mesure de mettre des types CF dans un Nsarray dans Objective-C en les jetant à ID . [myarray addObject: (id) mycgcolor]


Est-ce une définition documentée de anyobject ? J'accepte que devrait une définition de anyobject , mais je ne sais pas qu'il est actuellement est à Swift.


J'aimerais quelqu'un de mettre à jour leur réponse ou de poster une nouvelle réponse concernant ce qui se passait dans Beta 4 et Qu'est-ce qui a changé dans Beta 5 pour le réparer.



0
votes

de "en utilisant Swift avec cacao et objectif-c"

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.

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.

Entre-temps, vous pouvez utiliser la classe de cacao correspondante ou envelopper votre CGPATH dans un objet supplémentaire.


3 commentaires

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.



1
votes

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.

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.

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 au lieu de cgpath .


1 commentaires

Dans le compilateur Beta 4, vous pouvez éliminer le crash en déclarant la propriété comme final , 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 , qui déclenche à nouveau le crash.



0
votes
import UIKit

class MyClass: NSObject {

    var list = [CGPath]();

    override init() {
        list.append(CGPathCreateMutable());
    }
}

var instance = MyClass()
print(instance.list.count) // 1

1 commentaires

Ooh, a-t-ils réparé ??