Sök…


Anmärkningar

Mer information finns i Apples dokumentation om användning av Swift med kakao och Objekt-C .

Använda Swift-klasser från Objekt-C-kod

I samma modul

Inuti en modul som heter " MyModule " genererar Xcode en rubrik med namnet MyModule-Swift.h som exponerar offentliga Swift-klasser för Objekt-C. Importera den här rubriken för att använda Swift-klasserna:

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

Relevanta bygginställningar:

  • Objekt-C Generated Interface Header Name : styr namnet på det genererade Obj-C-huvudet.
  • Installera Objekt-C-kompatibilitetsrubrik : huruvida -Swift.h-huvudet ska vara en offentlig rubrik (för rammål).

bygga inställning skärmdump


I en annan modul

Använda @import MyFramework; importerar hela modulen, inklusive Obj-C-gränssnitt till Swift-klasser (om ovannämnda build-inställning är aktiverad).

Använda Objekt-C klasser från Swift-kod

Om MyFramework innehåller Objekt-C-klasser i sina offentliga rubriker (och paraplyhuvudet), är import MyFramework allt som behövs för att använda dem från Swift.

Överbryggande rubriker

En överbryggande rubrik gör ytterligare Objekt-C- och C-deklarationer synliga för Swift-kod. När du lägger till projektfiler kan Xcode erbjuda att skapa en överbryggande rubrik automatiskt:

överbryggande rubrikdialog

För att skapa en manuellt, ändra inställningen Objekt-C Bridging Header :

ange bildbeskrivning här

Inuti brygghuvudet, importera de filer som behövs för att använda från koden:

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

Genererat gränssnitt

Klicka på knappen Relaterade objekt (eller tryck på ⌃1) och välj sedan Genererat gränssnitt för att se Swift-gränssnittet som kommer att genereras från en Objekt-C-rubrik.

Ange en överbryggande rubrik till swiftc

-import-objc-header anger en rubrik för swiftc att importera:

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

Använd en modulkarta för att importera C-rubriker

En modulkarta kan helt enkelt import mymodule genom att konfigurera den för att läsa C-huvudfiler och få dem att visas som Swift-funktioner.

Placera en fil med namnet module.modulemap i en katalog med namnet mymodule :

katalogstruktur

Inuti modulen kartfil:

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

import sedan modulen:

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

Använd -I directory att berätta för swiftc var du kan hitta modulen:

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

Mer information om syntaxen för modulkartor finns i Clang-dokumentationen om modulkartor .

Finkornig interoperation mellan Objekt-C och Swift

När ett API är markerat med NS_REFINED_FOR_SWIFT kommer det att förinställas med två understreck ( __ ) när det importeras till Swift:

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

Det genererade gränssnittet ser ut så här:

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

Nu kan du byta ut API med en mer "Swifty" förlängning. I det här fallet kan vi använda ett valfritt returvärde och filtrera bort 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
}

I de flesta fall kanske du vill begränsa huruvida ett argument till en Objekt-C-funktion kan vara nil . Detta görs med hjälp av _Nonnull nyckelord, som kvalificerar alla pekare eller blockreferenser:

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

Med det skrivna ska kompilatorn avge ett fel när vi försöker överföra nil till den funktionen från vår Swift-kod:

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

Det motsatta av _Nonnull är _Nullable , vilket innebär att det är acceptabelt att passera nil i detta argument. _Nullable är också standard; men att specificera den uttryckligen möjliggör mer självdokumenterad och framtidssäker kod.

För att ytterligare hjälpa kompilatorn att optimera din kod, kanske du också vill ange om blocket flyr:

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

Med detta attribut lovar vi att inte spara blockreferensen och inte att ringa blocket efter att funktionen är klar.

Använd C-biblioteket

Med Swifts C-interoperabilitet kan du använda funktioner och typer från C-standardbiblioteket.

På Linux exponeras C-standardbiblioteket via Glibc modulen; på Apple-plattformar heter det 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow