Szukaj…


Uwagi

Więcej informacji można znaleźć w dokumentacji Apple na temat używania Swift z kakao i Objective-C .

Używanie klas Swift z kodu Objective-C

W tym samym module

Wewnątrz modułu o nazwie „ MyModule ” Xcode generuje nagłówek o nazwie MyModule-Swift.h który udostępnia publiczne klasy Swift obiektowi Objective-C. Zaimportuj ten nagłówek, aby użyć klas 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

Odpowiednie ustawienia kompilacji:

  • Nazwa nagłówka interfejsu wygenerowanego przez Objective-C : kontroluje nazwę generowanego nagłówka Obj-C.
  • Zainstaluj Object-C Compatibility Header : czy nagłówek -Swift.h powinien być nagłówkiem publicznym (dla celów ramowych).

zrzut ekranu ustawień kompilacji


W innym module

Korzystanie z @import MyFramework; importuje cały moduł, w tym interfejsy Obj-C do klas Swift (jeśli włączone jest wyżej wspomniane ustawienie kompilacji).

Korzystanie z klas Objective-C z kodu Swift

Jeśli MyFramework zawiera klasy Objective-C w swoich publicznych nagłówkach (i nagłówku parasola), to import MyFramework jest wszystkim, co jest konieczne, aby użyć ich z Swift.

Łączenie nagłówków

Mostkujący nagłówek sprawia, że dodatkowe deklaracje Objective-C i C są widoczne dla kodu Swift. Podczas dodawania plików projektu Xcode może zaoferować automatyczne utworzenie nagłówka pomostowego:

mostkowanie okna dialogowego nagłówka

Aby utworzyć go ręcznie, zmodyfikuj ustawienie kompilacji Nagłówka mostkowania Objective-C :

wprowadź opis zdjęcia tutaj

W nagłówku pomostowym zaimportuj pliki, które są potrzebne do użycia z kodu:

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

Wygenerowany interfejs

Kliknij przycisk Elementy powiązane (lub naciśnij ⌃1), a następnie wybierz opcję Generowany interfejs, aby wyświetlić interfejs Swift, który zostanie wygenerowany z nagłówka Cel-C.

Określ nagłówek mostkujący do swiftc

Flaga -import-objc-header określa nagłówek importu swiftc :

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

Użyj mapy modułów, aby zaimportować nagłówki C.

Mapa modułów może po prostu import mymodule , konfigurując go do odczytu plików nagłówka C i wyświetlania ich jako funkcji Swift.

Umieść plik o nazwie module.modulemap w katalogu o nazwie mymodule :

struktura katalogów

Wewnątrz pliku mapy modułu:

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

Następnie import moduł:

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

Użyj flagi -I directory aby powiedzieć swiftc gdzie znaleźć moduł:

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

Aby uzyskać więcej informacji na temat składni map modułów, zobacz dokumentację Clanga na temat map modułów .

Precyzyjna współpraca między Objective-C i Swift

Gdy interfejs API jest oznaczony NS_REFINED_FOR_SWIFT , po zaimportowaniu do Swift będzie poprzedzony dwoma podkreśleniami ( __ ):

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

Wygenerowany interfejs wygląda następująco:

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

Teraz możesz zastąpić interfejs API bardziej „szybkim” rozszerzeniem. W takim przypadku możemy użyć opcjonalnej wartości zwracanej, odfiltrowując 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
}

W większości przypadków możesz chcieć ograniczyć, czy argument funkcji Objective-C może być nil . Odbywa się to za pomocą słowa kluczowego _Nonnull , które kwalifikuje dowolny wskaźnik lub odwołanie do bloku:

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

Po napisaniu tego kompilator będzie emitował błąd za każdym razem, gdy spróbujemy przekazać nil do tej funkcji z naszego kodu Swift:

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

Przeciwieństwem _Nonnull jest _Nullable , co oznacza, że dopuszczalne jest podanie wartości nil w tym argumencie. _Nullable jest również ustawieniem domyślnym; jednak wyraźne określenie go pozwala na uzyskanie bardziej udokumentowanego i przyszłościowego kodu.

Aby dodatkowo pomóc kompilatorowi w optymalizacji kodu, możesz również określić, czy blok ucieka:

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

Dzięki temu atrybutowi obiecujemy nie zapisywać odwołania do bloku i nie wywoływać bloku po zakończeniu wykonywania funkcji.

Użyj standardowej biblioteki C.

Współdziałanie C Swift umożliwia korzystanie z funkcji i typów ze standardowej biblioteki C.

W systemie Linux biblioteka standardowa C jest udostępniana za pośrednictwem modułu Glibc ; na platformach Apple nazywa się to 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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow