Zoeken…


Opmerkingen

Raadpleeg de documentatie van Apple over het gebruik van Swift met Cocoa en Objective-C voor meer informatie.

Swift-klassen uit Objective-C-code gebruiken

In dezelfde module

Binnen een module met de naam " MyModule " genereert Xcode een header met de naam MyModule-Swift.h die openbare Swift-klassen blootstelt aan Objective-C. Importeer deze header om de Swift-klassen te gebruiken:

// 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

Relevante build-instellingen:

  • Objective-C Generated Interface Header Name : bepaalt de naam van de gegenereerde Obj-C-header.
  • Installeer Objective-C Compatibiliteitskoptekst : of de -Swift.h-kop een openbare kop moet zijn (voor kaderdoelen).

build instelling screenshot


In een andere module

@import MyFramework; importeert de hele module, inclusief Obj-C-interfaces naar Swift-klassen (als de bovengenoemde build-instelling is ingeschakeld).

Objective-C-klassen van Swift-code gebruiken

Als MyFramework Objective-C-klassen in de openbare kopteksten (en de paraplustekst) bevat, is het import MyFramework alles wat nodig is om ze van Swift te gebruiken.

Kopteksten overbruggen

Een overbruggende kop maakt extra Objective-C- en C-aangiften zichtbaar voor Swift-code. Bij het toevoegen van projectbestanden kan Xcode aanbieden om automatisch een bridging header te maken:

overbruggende koptekst dialoog

Als u er handmatig een wilt maken, wijzigt u de build-instelling van Objective-C Bridging Header :

voer hier de afbeeldingsbeschrijving in

Importeer binnen de overbruggende header welke bestanden nodig zijn om te gebruiken vanuit code:

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

Gegenereerde interface

Klik op de knop Gerelateerde items (of druk op ⌃1) en selecteer vervolgens Gegenereerde interface om de Swift-interface te bekijken die wordt gegenereerd vanuit een Objective-C-header.

Geef een brugkop op voor swiftc

De vlag -import-objc-header geeft een header aan die swiftc moet importeren:

// 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)

Gebruik een modulekaart om C-headers te importeren

Een modulekaart kan eenvoudig import mymodule door het te configureren om C-headerbestanden te lezen en ze als Swift-functies te laten verschijnen.

Plaats een bestand met de naam module.modulemap in een map met de naam mymodule :

mapstructuur

Binnen het module mapbestand:

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

import de module:

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

Gebruik de -I directory vlag om swiftc te vertellen waar de module te vinden is:

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

Zie de Clang-documentatie over modulekaarten voor meer informatie over de syntaxis van de modulekaart .

Fijnmazige samenwerking tussen Objective-C en Swift

Wanneer een API is gemarkeerd met NS_REFINED_FOR_SWIFT , wordt deze voorafgegaan door twee onderstrepingstekens ( __ ) wanneer deze wordt geïmporteerd in Swift:

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

De gegenereerde interface ziet er zo uit:

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

Nu kunt u de API vervangen door een meer "Swifty" -extensie. In dit geval kunnen we een optionele retourwaarde gebruiken, waarbij NSNotFound wordt uitgefilterd :

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
}

In de meeste gevallen wilt u misschien beperken of een argument voor een Objective-C-functie nil kan zijn. Dit wordt gedaan met het trefwoord _Nonnull , waarmee elke aanwijzer of blokverwijzing in aanmerking komt:

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

Met dat geschreven, zal de compiler een foutmelding geven telkens als we proberen nil door te geven aan die functie vanuit onze Swift-code:

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

Het tegenovergestelde van _Nonnull is _Nullable , wat betekent dat het acceptabel is om nil in dit argument. _Nullable is ook de standaard; als u dit expliciet opgeeft, kunt u echter meer zelfgedocumenteerde en toekomstbestendige code gebruiken.

Om de compiler verder te helpen bij het optimaliseren van uw code, wilt u misschien ook aangeven of het blok ontsnapt:

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

Met dit kenmerk beloven we de blokreferentie niet op te slaan en het blok niet aan te roepen nadat de functie is voltooid.

Gebruik de C-standaardbibliotheek

Met de C-interoperabiliteit van Swift kunt u functies en typen uit de C-standaardbibliotheek gebruiken.

Op Linux is de C-standaardbibliotheek zichtbaar via de Glibc module; op Apple-platforms heet het 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow