Recherche…


Remarques

Pour plus d'informations, consultez la documentation d'Apple sur l' utilisation de Swift avec Cocoa et Objective-C .

Utiliser les classes Swift du code Objective-C

Dans le même module

Dans un module nommé " MyModule ", Xcode génère un en-tête nommé MyModule-Swift.h qui expose les classes Swift publiques à Objective-C. Importez cet en-tête pour utiliser les classes Swift:

// MySwiftClass.swift in MyApp
import Foundation

// The class must be `public` to be visible, unless this target also has a bridging header
public class MySwiftClass: NSObject {
    // ...
}
// MyViewController.m in MyApp

#import "MyViewController.h"
#import "MyApp-Swift.h"                    // import the generated interface
#import <MyFramework/MyFramework-Swift.h>  // or use angle brackets for a framework target

@implementation MyViewController
- (void)demo {
    [[MySwiftClass alloc] init];  // use the Swift class
}
@end

Paramètres de construction pertinents:

  • Nom de l'en-tête de l'interface générée par Objective-C : contrôle le nom de l'en-tête Obj-C généré.
  • Installez Objective-C Compatibility Header : si l'en-tête -Swift.h doit être un en-tête public (pour les cibles du framework).

capture d'écran


Dans un autre module

Utiliser @import MyFramework; importe l'ensemble du module, y compris les interfaces Obj-C, aux classes Swift (si le paramètre de construction susmentionné est activé).

Utilisation de classes Objective-C à partir du code Swift

Si MyFramework contient des classes Objective-C dans ses en-têtes publiques (et dans l'en-tête parapluie), il import MyFramework pour les utiliser depuis Swift.

Passerelles

Un en- tête de pontage rend les déclarations Objective-C et C supplémentaires visibles pour le code Swift. Lors de l'ajout de fichiers de projet, Xcode peut proposer de créer automatiquement un en-tête de pontage:

dialogue d'en-tête de pontage

Pour en créer un manuellement, modifiez le paramètre de génération Objective-C Bridging Header :

entrer la description de l'image ici

A l'intérieur de l'en-tête de pontage, importez les fichiers nécessaires à l'utilisation du code:

// MyApp-Bridging-Header.h
#import "MyClass.h"  // allows code in this module to use MyClass

Interface générée

Cliquez sur le bouton Éléments associés (ou appuyez sur ⌃1), puis sélectionnez Interface générée pour voir l'interface Swift générée à partir d'un en-tête Objective-C.

Spécifiez un en-tête de pontage pour swiftc

Le -import-objc-header spécifie un en-tête pour swiftc à importer:

// defs.h
struct Color {
    int red, green, blue;
};

#define MAX_VALUE 255
// demo.swift
extension Color: CustomStringConvertible {  // extension on a C struct
    public var description: String {
        return "Color(red: \(red), green: \(green), blue: \(blue))"
    }
}
print("MAX_VALUE is: \(MAX_VALUE)")  // C macro becomes a constant
let color = Color(red: 0xCA, green: 0xCA, blue: 0xD0)  // C struct initializer
print("The color is \(color)")
$ swiftc demo.swift -import-objc-header defs.h && ./demo
MAX_VALUE is: 255
The color is Color(red: 202, green: 202, blue: 208)

Utiliser une carte de module pour importer des en-têtes C

Une carte de module peut simplement import mymodule en le configurant pour lire les fichiers d'en-tête C et les faire apparaître comme des fonctions Swift.

Placez un fichier nommé module.modulemap dans un répertoire nommé mymodule :

structure de répertoire

Dans le fichier de carte du module:

// mymodule/module.modulemap
module mymodule {
    header "defs.h"
}

Puis import le module:

// demo.swift
import mymodule
print("Empty color: \(Color())")

Utilisez l'indicateur de -I directory pour indiquer à swiftc où trouver le module:

swiftc -I . demo.swift   # "-I ." means "search for modules in the current directory"

Pour plus d'informations sur la syntaxe de la carte de module, consultez la documentation de Clang sur les cartes de module .

Interaction fine entre Objective-C et Swift

Lorsqu'une API est marquée avec NS_REFINED_FOR_SWIFT , elle sera préfixée par deux NS_REFINED_FOR_SWIFT soulignement ( __ ) lors de son importation dans Swift:

@interface MyClass : NSObject
- (NSInteger)indexOfObject:(id)obj NS_REFINED_FOR_SWIFT;
@end

L' interface générée ressemble à ceci:

public class MyClass : NSObject {
    public func __indexOfObject(obj: AnyObject) -> Int
}

Vous pouvez maintenant remplacer l’API par une extension plus "Swifty". Dans ce cas, nous pouvons utiliser une valeur de retour facultative , en filtrant NSNotFound :

extension MyClass {
    // Rather than returning NSNotFound if the object doesn't exist,
    // this "refined" API returns nil.
    func indexOfObject(obj: AnyObject) -> Int? {
        let idx = __indexOfObject(obj)
        if idx == NSNotFound { return nil }
        return idx
    }
}

// Swift code, using "if let" as it should be:
let myobj = MyClass()
if let idx = myobj.indexOfObject(something) {
    // do something with idx
}

Dans la plupart des cas , vous pouvez limiter ou non un argument à une fonction Objective-C pourrait être nil . Ceci est fait en utilisant le mot clé _Nonnull , qui qualifie tout pointeur ou référence de bloc:

void
doStuff(const void *const _Nonnull data, void (^_Nonnull completion)())
{
    // complex asynchronous code
}

Avec cela écrit, le compilateur doit émettre une erreur chaque fois que nous essayons de passer nil à cette fonction à partir de notre code Swift:

doStuff(
    nil,  // error: nil is not compatible with expected argument type 'UnsafeRawPointer'
    nil)  // error: nil is not compatible with expected argument type '() -> Void'

Le contraire de _Nonnull est _Nullable , ce qui signifie qu'il est acceptable de passer nil dans cet argument. _Nullable est aussi la valeur par défaut. Cependant, le spécifier explicitement permet un code plus auto-documenté et à l'épreuve du futur.

Pour aider le compilateur à optimiser votre code, vous pouvez également spécifier si le bloc est échappé:

void
callNow(__attribute__((noescape)) void (^_Nonnull f)())
{
    // f is not stored anywhere
}

Avec cet attribut, nous promettons de ne pas enregistrer la référence de bloc et de ne pas appeler le bloc une fois l'exécution de la fonction terminée.

Utilisez la bibliothèque standard C

L'interopérabilité C de Swift vous permet d'utiliser des fonctions et des types de la bibliothèque standard C.

Sous Linux, la bibliothèque standard C est exposée via le module Glibc ; sur les plateformes Apple, cela s'appelle Darwin .

#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
import Darwin
#elseif os(Linux)
import Glibc
#endif

// use open(), read(), and other libc features


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow