Le code objective-c peut-il appeler l'extension Swift sur la classe?

94

J'ai cherché quelques articles, je pense que je ne peux pas écrire une extension sous swift, et l'appeler à partir du code Objective-C, non?

@objc comme les attributs ne supportent que les méthodes, la classe, les protocoles?

sprhawk
la source
1
Pourquoi ne pas essayer?
HAS
7
ide s'est plaint d'erreur, mais je veux avoir une réponse définitive.
sprhawk

Réponses:

84

Vous pouvez écrire une extension Swift et l'utiliser dans du code Objective-C. Testé avec XCode 6.1.1.

Tout ce que vous avez à faire est:

  • créez votre extension dans Swift (sans @objcannotation)

  • #import "ProjectTarget-Swift.h" dans votre classe Objective-C (où "ProjectTarget" représente la cible XCode à laquelle l'extension Swift est associée)

  • appeler les méthodes depuis l'extension Swift

Mise à jour: à partir de @Rizwan Ahmed mentionné, vous devez ajouter une @objcannotation:

Depuis Swift 4.0.3, l'annotation @objc est nécessaire si vous souhaitez utiliser l'extension dans les fichiers de classe Objective C.

Marius Bardan
la source
6
J'ai fait exactement cela mais c'est toujours une erreur de compilation. Hmmm. EDIT: J'ai importé mon en-tête de pont, au lieu de "ProjectTarget-Swift.h". Der.
Jason Renaldo
Les deux sont des en-têtes de pontage. La différence est que l'un sert à utiliser le code Swift dans ObjC et l'autre à utiliser le code ObjC dans Swift. L'en-tête Swift est invisible. L'autre, devrait être géré par vous.
marius bardan
William Hu, voyez la réponse de mclaughlinj!
appleitung
39
Depuis Swift 4.0.3, l'annotation @objc est nécessaire si vous souhaitez utiliser l'extension dans les fichiers de classe Objective C.
Rizwan Ahmed
68

J'ai découvert que dans Swift 4.0, je devais ajouter @objcdevant mon mot-clé d' extension pour que les méthodes d'extension Swift deviennent visibles par une instance de la classe Objc que j'étendais.

En bref:

Configuration de la configuration des fichiers:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

Dans CustomClassExtension:

@objc extension CustomClass
{
    func method1() 
    {
        ...
    }
}

Dans mon AppDelegate.m:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];
Andrey P.
la source
2
Si une méthode utilise des génériques, elle ne peut pas être utilisée par Objective-C et vous devrez ajouter l' @nonobjcannotation.
ThomasW
Juste une remarque, @objcMembers ne fonctionne pas dans ce cas. Je ne sais pas pourquoi .. :-(
Raunak
46

Cette solution fonctionne pour Swift 2.2 et Swift 3 . Notez que seules les extensions pour les classes (pas pour les structs ou les enums) seront accessibles depuis Objective-C.

import UIKit

extension UIColor {

    //Custom colours
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

Puis # import "ProductModuleName-Swift.h" dans votre fichier ObjC.

Swift 4

extension UIColor {

    // As of Swift 4.0.3, the @objc annotation is needed if you want to use the extension in Objective-C files
    @objc
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}
Foti Dim
la source
Ce n'est pas "YourProjectsNameHere ..." mais plutôt "YourTargetsNameHere ...": pour partager des cibles, vous devez le verrouiller au nom: dr2050.postach.io/post
Dan Rosenstark
1
@DanRosenstark Vous avez raison. Je le change en "ProductModuleName-Swift.h" comme Apple le suggère: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Foti Dim
1
Fonctionne bien pour Swift 3.
Viktor Kucera
Y a-t-il une raison pour laquelle vous dites que publicc'est nécessaire? Fonctionne très bien sans publicmodificateur pour moi. Supposons-nous que l'extension ne fait pas partie du même projet mais qu'elle est importée d'un autre projet?
Lee Kang
Dois-je utiliser un en-tête de pontage?
jegadeesh
42

Comme indiqué dans les autres réponses, l'importation de l'en-tête Swift généré fonctionne dans la plupart des cas .

Une exception à cela est lorsque la catégorie est définie sur un type ponté (c'est-à-dire que l'extension est définie sur Stringet non NSString). Ces catégories ne seront pas automatiquement reliées à leurs homologues Objective-C. Pour contourner ce problème, vous devrez soit utiliser le type Objective-C (et convertir la valeur de retour dans votre code Swift avec as String), soit définir une extension pour les types Swift et Objective-C.

mclaughlinj
la source
2
En ajoutant à la réponse ci-dessus, vous devez rendre votre extension swift publique et définir son type comme NSString, par exemple public extension NSString. Si vous obtenez un identifiant non résolu ou une erreur similaire au moment de la compilation, vous pouvez reconstituer à nouveau String par exemple let sVal = self as String, puis appeler le code nécessaire sursVal
RunLoop
@RunLoop en fait, vous n'avez pas besoin de public, cela fonctionnera sans spécificateur de portée. Et cela (l'exportation vers Obj-C, je veux dire) ne fonctionne pas pour les chaînes, car ce sont des structures, pas des classes et qu'elles ne sont disponibles que depuis Swift. Donc, oui - vous pouvez écrire une extension pour NSString et utiliser cast, ou écrire des extensions, comme mclaughlinjdit, pour la classe NSString et la structure String
Alex Nazarsky
3

Importez l'en - tête "#import" ProductModuleName-Swift.h " dans le fichier objective-c et ajoutez @objc en face de votre extension dans le fichier swift. Cela fonctionnera bien dans swift 4.2 et swift 5

Ranjani
la source