Jak wywołać kod celu C w Swift?

974

Jak w Swift wywołuje się kod celu C?

Apple wspomniał, że mogą one współistnieć w jednej aplikacji, ale czy to oznacza, że ​​można technicznie ponownie użyć starych klas stworzonych w Objective-C, budując nowe klasy w Swift?

David Mulder
źródło
13
Zobacz przewodnik Apple dotyczący używania Swift z kakao i Objective-C .
rickster
10
Ciekawe, że to pytanie zyskuje tak wiele pozytywnych opinii i nagrody. Kiedy to zobaczyłem, pomyślałem: RTFM. Zgodnie z założeniami, naprawdę nie wykazują żadnych badań, ponieważ obecnie istnieją tylko dwa lub trzy zasoby, które oficjalnie dokumentują Swift, a jeden z nich jest w pełni poświęcony właśnie temu (i jest powiązany z pierwszym komentarzem).
Plik analogowy
6
@EvolGate: czego dokładnie brakuje w celu C, co uniemożliwia mu bycie językiem niezależnym od platformy? Język i standardowe biblioteki językowe są oprogramowaniem typu open source. Możesz używać Celu C w Windowsie, OS X, Linux, BSD, Solaris i dowolnej innej platformie obsługiwanej przez GCC lub LLVM. Możesz łatwo przenieść Objective C na dowolną platformę z przyzwoitym kompilatorem C, nawet jeśli nie jest obsługiwany przez GCC ani LLVM. Nie rozumiem, jak mogłaby być bardziej niezależna od platformy.
Plik analogowy
2
@DavidMulder: Czy sekcja „Rozumowanie” jest nadal potrzebna?
franck

Odpowiedzi:

1393

Używanie klas Objective-C w Swift

Jeśli masz istniejącą klasę, której chcesz użyć, wykonaj krok 2, a następnie przejdź do kroku 5 . (W niektórych przypadkach musiałem dodać jawny #import <Foundation/Foundation.hplik do starszego pliku Objective-C).

Krok 1: Dodaj implementację celu C - .m

Dodaj .mplik do swojej klasy i nazwij go CustomObject.m.

Krok 2: Dodaj nagłówek pomostowy

Podczas dodawania .mpliku najprawdopodobniej wyświetli się następujący monit:

Okno dialogowe w stylu arkusza macOS z Xcode z pytaniem, czy „chcesz skonfigurować nagłówek mostkujący Objective-C”

Kliknij Tak !

Jeśli nie zobaczyłeś monitu lub przypadkowo usunąłeś nagłówek pomostowy, dodaj nowy .hplik do projektu i nazwij go <#YourProjectName#>-Bridging-Header.h.

W niektórych sytuacjach, szczególnie podczas pracy ze strukturami Objective-C, nie dodajesz wyraźnie klasy Objective-C i Xcode nie może znaleźć linkera. W takim przypadku utwórz .hplik o nazwie jak wspomniano powyżej, a następnie upewnij się, że łączysz jego ścieżkę w ustawieniach projektu docelowego w następujący sposób:

Animacja pokazująca powyższy akapit

Uwaga:

Najlepszą praktyką jest łączenie projektu za pomocą $(SRCROOT)makra, aby przeniesienie projektu lub praca nad nim przy użyciu zdalnego repozytorium nadal działała. $(SRCROOT)może być uważany za katalog zawierający plik .xcodeproj. Może to wyglądać tak:

$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h

Krok 3: Dodaj nagłówek celu C - .h

Dodaj kolejny .hplik i nazwij go CustomObject.h.

Krok 4: Zbuduj swoją klasę Objective-C

W CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

W CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

- (void) someMethod {
    NSLog(@"SomeMethod Ran");
}

@end

Krok 5: Dodaj klasę do nagłówka pomostowego

W YourProject-Bridging-Header.h:

#import "CustomObject.h"

Krok 6: Użyj swojego obiektu

W SomeSwiftFile.swift:

var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

Nie ma potrzeby jawnego importowania; po to jest nagłówek pomostowy.

Używanie szybkich klas w celu C

Krok 1: Utwórz nową klasę Swift

Dodaj .swiftplik do projektu i nazwij go MySwiftObject.swift.

W MySwiftObject.swift:

import Foundation

@objc(MySwiftObject)
class MySwiftObject : NSObject {

    @objc
    var someProperty: AnyObject = "Some Initializer Val" as NSString

    init() {}

    @objc
    func someFunction(someArg: Any) -> NSString {
        return "You sent me \(someArg)"
    }
}

Krok 2: Zaimportuj pliki Swift do klasy ObjC

W SomeRandomClass.m:

#import "<#YourProjectName#>-Swift.h"

Plik: <#YourProjectName#>-Swift.hpowinien już zostać utworzony automatycznie w twoim projekcie, nawet jeśli go nie widzisz.

Krok 3: Użyj swojej klasy

MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);

NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];

NSLog(@"RetString: %@", retString);

Uwagi:

  1. Jeśli uzupełnianie kodu nie działa zgodnie z oczekiwaniami, spróbuj uruchomić szybką kompilację, Raby pomóc Xcode znaleźć część kodu Objective-C z kontekstu Swift i odwrotnie.

  2. Jeśli dodasz .swiftplik do starszego projektu i otrzymasz błąd dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, spróbuj całkowicie zrestartować Xcode .

  3. Chociaż pierwotnie było możliwe użycie czystych klas Swift (nie potomków NSObject), które są widoczne dla Objective-C przy użyciu @objcprefiksu, nie jest to już możliwe. Teraz, aby być widocznym w Objective-C, obiekt Swift musi albo być klasą zgodną z NSObjectProtocol(najprostszym sposobem na to jest dziedziczenie NSObject), albo być enumoznaczony @objcsurową wartością jakiegoś typu liczby całkowitej Int. Możesz przeglądać historię edycji dla przykładu kodu Swift 1.x używającego @objcbez tych ograniczeń.

Logan
źródło
5
Ważne jest, aby adnotować metody za pomocą @objc, w przeciwnym razie metody Swift nie będą widoczne w Objective-C.
Tomáš Linhart
29
Masz rację. Musisz to określić tylko wtedy, gdy nie używasz obiektów kakaowych. Aby była dostępna i użyteczna w Objective-C, klasa Swift musi być potomkiem klasy Objective-C lub musi być oznaczona @objc.
Tomáš Linhart
2
@MarkusRautopuro - Mam go stąd: developer.apple.com/library/prerelease/ios/documentation/Swift/… "
Logan
2
Zobacz także: WWDC 2014 Sesja 406: Integracja Swift z Objective-C
Stuart M
6
W przypadku importowania frameworka Objective C do Swift, należy zaimportować wszystkie frameworki, od których zależy frameworku Obj C do projektu (w Fazach kompilacji -> Połącz pliki binarne z bibliotekami), a następnie dodaj # importu tych plików do pliku nagłówka prefiksu, który należy dodać do projektu w ustawieniach kompilacji (w polu Nagłówek prefiksu). Obejmuje to frameworki takie jak UIKit i Foundation, nawet jeśli są już używane z poziomu Swift. To mnie potknęło godzinami i wydaje się, że nikt nie udokumentował tych kroków.
user1021430,
121

Zobacz przewodnik Apple dotyczący używania Swift z kakao i Objective-C . Ten przewodnik obejmuje korzystanie z kodu Objective-C i C z Swift i vice versa oraz zawiera zalecenia dotyczące konwertowania projektu lub mieszania i dopasowywania części Objective-C / C i Swift w istniejącym projekcie.

Kompilator automatycznie generuje składnię Swift do wywoływania funkcji C i metod Objective-C. Jak widać w dokumentacji, cel C:

UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];

zamienia się w ten kod Swift:

let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)

Xcode wykonuje również to tłumaczenie w locie - możesz użyć Otwórz szybko podczas edycji pliku Swift i wpisać nazwę klasy Objective-C, a przeniesie Cię to do nagłówka klasy Swift-ified. (Można to również uzyskać, klikając cmd symbol API w pliku Swift). Cała dokumentacja referencyjna API w bibliotekach programistów iOS 8 i OS X 10.10 (Yosemite) jest widoczna zarówno w Objective-C, jak i Swift formularze (np UIView.).

Rickster
źródło
3
Bezpośredni link do dokumentacji Apple, jak zintegrować Swift z istniejącym projektem: developer.apple.com/library/prerelease/ios/documentation/Swift/…
skywinder
Jeśli interesuje nas, dlaczego pliki nagłówkowe są potrzebne i jak są wykorzystywane w fazie łączenia, przeczytaj ten Podręcznik ręczny Swift: Zrozumienie budowy kompilacji Swift / Objective-C
Honey,
62

Oto instrukcje krok po kroku dotyczące używania kodu Objective-C (w tym przypadku frameworku dostarczonego przez firmę zewnętrzną) w projekcie Swift:

  1. Dodaj dowolny plik Objective-C do projektu Swift , wybierając Plik -> Nowy -> Nowy plik -> Plik Objective-C. Po zapisaniu Xcode zapyta, czy chcesz dodać nagłówek pomostowy . Wybierz „ Tak ”. (źródło: derrrick.com )Gif: dodawanie pustego pliku do projektu i generowanie nagłówka pomostowego

W prostych krokach:

  1. Pojawi się monit, a następnie kliknij przycisk OK ... Jeśli się nie pojawi, wówczas tworzymy go ręcznie, jak poniżej: Utwórz jeden plik nagłówka ze źródła iOS i nadaj nazwę ProjectName-Bridging-Header (przykład: Test -Bridging-Header), a następnie przejdź do kompilacji w kodzie kompilatora Swift -> Most Cel-C dodaj nazwę mostu Cel-C .. (Test / Test-Bridging-Header.h). Tak, to koniec.

  2. Opcjonalnie usuń dodany plik Objective-C (o nazwie „cokolwiek” na powyższym obrazku GIF). Już go nie potrzebujesz.

  3. Otwórz mostkowy plik nagłówkowy - nazwa pliku ma postać [YourProject] -Bridging-Header.h . Zawiera komentarz dostarczony przez Xcode. Dodaj wiersz kodu dla pliku Objective-C, który chcesz dołączyć , na przykład frameworku innej firmy. Na przykład, aby dodać Mixpanel do swojego projektu, musisz dodać następujący wiersz kodu do mostkowego pliku nagłówkowego:

    #import „Mixpanel.h”
  4. Teraz w dowolnym pliku Swift możesz użyć istniejącego kodu Objective-C, w składni Swift (w przypadku tego przykładu i możesz wywołać metody Mixpanel SDK itp.). Musisz zapoznać się ze sposobem, w jaki Xcode tłumaczy Objective-C na Swift. Poradnik Apple'a to szybka lektura. Lub zobacz tę odpowiedź, aby uzyskać niepełne podsumowanie.

Przykład dla Mixpanel:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    Mixpanel.sharedInstanceWithToken("your-token")
    return true
}

Otóż ​​to!

Uwaga: Jeśli usuniesz plik nagłówka pomostowego z projektu , przejdź do Ustawień kompilacji i usuń wartość „ Celujący nagłówek pomostowy C ” w „Kompilatorze Swift - Generowanie kodu”.

Derrrick
źródło
39

Możesz przeczytać miły post Swift & Cocoapods . Zasadniczo musimy utworzyć mostkowy plik nagłówkowy i umieścić tam wszystkie nagłówki Cel-C. A następnie musimy odwołać się do tego w naszych ustawieniach kompilacji. Następnie możemy użyć kodu Objective-C.

let manager = AFHTTPRequestOperationManager()
manager.GET(
  "http://example.com/resources.json",
  parameters: nil,
  success: { (operation: AFHTTPRequestOperation!,
              responseObject: AnyObject!) in
      println("JSON: " + responseObject.description)
  },
  failure: { (operation: AFHTTPRequestOperation!,
              error: NSError!) in
      println("Error: " + error.localizedDescription)
  })

Zobacz także dokument Apple'a Używanie Swift z kakao i Objective-C .

Jake Lin
źródło
25

Napisałem prosty projekt Xcode 6, który pokazuje, jak mieszać kod C ++, Objective-C i Swift:

https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console

W szczególności przykład wywołuje funkcję Objective-C i C ++ od Swift .

Kluczem jest utworzenie wspólnego nagłówka Project-Bridging-Header.h i umieszczenie tam nagłówków Objective-C.

Pobierz projekt jako kompletny przykład.

Gian Luigi Romita
źródło
24

Jeszcze jedno chciałbym tutaj dodać:

Jestem bardzo wdzięczny za odpowiedź @ Logana. Bardzo pomaga w tworzeniu pliku pomostu i ustawień.

Ale po wykonaniu wszystkich tych kroków nadal nie dostaję klasy Objective-C w Swift.

Korzystałem z cocoapodsbiblioteki i zintegrowałem ją z moim projektem. Który jestpod "pop" .

Jeśli więc używasz kapsułów Celu-C w Swift, może istnieć szansa, że ​​nie będziesz w stanie dostać importsię do Swift lub klas.

Prostą rzeczą, którą musisz zrobić, to:

  1. Przejdź do <YOUR-PROJECT>-Bridging-Headerpliku i
  2. Zamień instrukcję #import <ObjC_Framework>na@import ObjC_Framework

Na przykład: (Pop Library)

Zastąpić

#import <pop/POP.h>

z

@import pop;

Użyj, clang importgdy #importnie działa.

Kampai
źródło
Użyj importu clang, gdy #import nie działa. co? Nie powiedziałeś tylko, że powinniśmy używać @import?
Honey
22

Cytat z dokumentacji :

Dowolną platformę Objective-C (lub bibliotekę C), która jest dostępna jako moduł, można zaimportować bezpośrednio do Swift. Obejmuje to wszystkie frameworki systemu Objective-C - takie jak Foundation, UIKit i SpriteKit - a także wspólne biblioteki C dostarczane z systemem. Na przykład, aby zaimportować Foundation, po prostu dodaj tę instrukcję importu na górze pliku Swift, w którym pracujesz:

import Foundation

Ten import powoduje, że wszystkie interfejsy API Fundacji - w tym NSDate, NSURL, NSMutableData oraz wszystkie ich metody, właściwości i kategorie - są bezpośrednio dostępne w Swift.

Gergo Erdosi
źródło
12

Tylko uwaga dla każdego, kto próbuje dodać bibliotekę Objective-C do Swift: Powinieneś dodać -ObjC w Ustawieniach kompilacji -> Łączenie -> Inne flagi Linkera .

david72
źródło
Dlaczego? Dodaj informacje o tym, co robi ta flaga i dlaczego należy ją dodać.
Johan Karlsson,
9

Po utworzeniu nagłówka Bridging przejdź do Build Setting => Wyszukaj „Cel-C Bridging Header”.

Tuż poniżej znajduje się plik „„ Nazwa nagłówka interfejsu generowanego przez Objective-C ””.

Zaimportuj ten plik do kontrolera widoku.

Przykład: W moim przypadku: „Dauble-Swift.h”

eEter opis zdjęcia tutaj

Avijit Nagare
źródło
5

Kliknij menu Nowy plik i wybierz plik wybierz język Cel. W tym momencie automatycznie generuje plik „Objective-C Bridging Header”, który służy do zdefiniowania nazwy klasy.

„Nagłówek mostkujący Objective-C” w „Swift Compiler - Generowanie kodu”.

Yogesh Shelke
źródło
3
  1. Utwórz plik .h z NewFile -> Źródło -> plik nagłówka
  2. Następnie zapisz nazwę pliku Your_Target_Name-Bridging-Header.h Ludzie tutaj często popełniają błąd, przyjmując nazwę swojego projektu, ale powinna to być nazwa celu projektu, jeśli w przypadku, gdy oba są różne, ogólnie są one takie same.
  3. Następnie w ustawieniach kompilacji wyszukaj nagłówek mostkujący Cel-C flagę i podaj adres swojego nowo utworzonego pliku pomostowego, możesz to zrobić, klikając plik prawym przyciskiem myszy -> pokaż w wyszukiwarce -> przeciągnij plik w pole tekstowe, a następnie adres zostanie być zaludnionym.
  4. Korzystanie z #import Your_Objective-C_file.h
  5. W pliku szybkim można uzyskać dostęp do pliku ObjC, ale tylko w szybkim języku.
Nish
źródło
3

wprowadź opis zdjęcia tutajDodałem projekt na github, który zawiera małą próbkę do szybkiego wywołania kodu celu c.

Wywołaj klasę ObjectiveC z szybkiego

CrazyPro007
źródło
UWAGA: - Kiedy tworzysz klasę Objc w szybkim projekcie, xcode prosi o automatyczne mostkowanie klasy. Bez obaw :)
CrazyPro007
3

W projekcie Swift 4.2.1 w Xcode 10.1 możesz łatwo dodać plik Objective-C. Wykonaj poniższe czynności, aby połączyć plik Objective-C z projektem Swift.

Krok_01: Utwórz nowy projekt Xcode za pomocą języka Swift:

File> New> Project> objc.

Krok_02: W projekcie Swift dodaj nowy plik Objective-C:

File> New> File...> macOS> Objective-C File.

Krok_03: Jeśli dodasz nowy plik Objective-C do projektu Swift za pierwszym razem, Xcode zapyta:

Would you like to configure an Objective-C bridging header?

wprowadź opis zdjęcia tutaj

Krok_04: Wybierz opcję:

Create Bridging Header.

Krok_05: Odpowiedni plik zostanie wygenerowany o nazwie:

Objc-Bridging-Header.h.

wprowadź opis zdjęcia tutaj

Krok_06: Teraz potrzebujesz ścieżki pliku mostu w nagłówku mostu. W Nawigatorze projektów kliknij projekt o nazwie, objca następnie wybierz:

Build Settings> Objective-C Bridging Header> Objc-Bridging-Header.h.

Krok_07: Przeciągnij i upuść swoje Objc-Bridging-Header.hw to pole, aby wygenerować ścieżkę do pliku.

wprowadź opis zdjęcia tutaj

Krok_08: Otwórz Objc-Bridging-Header.hplik i zaimportuj plik Objective-C, którego chcesz użyć w pliku Swift.

#import "SpecialObjcFile.m"

Oto treść SpecialObjcFile.m:

#import <Foundation/Foundation.h>

@interface Person: NSObject {
@public
    bool busy;
}
@property
    bool busy;
@end

Krok_09: Teraz w swoim pliku Swift możesz użyć klasy Objective-C:

override func viewDidLoad() {
    super.viewDidLoad()
    let myObjcContent = Person()
    print(myObjcContent.busy)
}

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Andy
źródło
1

Odpowiedź Logans działa dobrze, z wyjątkiem najnowszych, Swift 5że daje błąd kompilatora. Oto poprawka dla osób pracujących nad Swift 5.

Szybki 5

import Foundation

class MySwiftObject : NSObject {

    var someProperty: AnyObject = "Some Initializer Val" as AnyObject

    override init() {}

    func someFunction(someArg:AnyObject) -> String {
        let returnVal = "You sent me \(someArg)"
        return returnVal
    }
}
Sazzad Hissain Khan
źródło
1

Szybki konsument, producent Objective-C

  1. Dodaj nagłówek .hi .mpliki implementacji - plik klasy kakao (cel C)
    Na przykładMyFileName

  2. skonfiguruj nagłówek mostkujący
    Kiedy zobaczysz Would you like to configure an Objective-C bridging headerkliknij - Tak

    • <target_name>-Bridging-Header.h zostanie wygenerowany automatycznie
    • Ustawienia kompilacji -> Nagłówek mostkujący Cel-C
  3. Dodaj klasę do Bridging-Header
    W <target_name>-Bridging-Header.hdodaj linię#import "<MyFileName>.h"

PS Jeśli chcesz dodać istniejące pliki Objective-C do projektu Swift, dodaj je Bridging-Header.hwcześniej

Cel C konsument, producent Swift

  1. Dodaj <MyFileName>.swifti rozszerzaNSObject

  2. Zaimportuj pliki Swift do klasy ObjC
    Dodaj #import "<#YourProjectName#>-Swift.h"do pliku Objective-C

  3. Oznacz publiczny kod Swift [@objc i @objcMembers]

yoAlex5
źródło
0

Apple przedstawił oficjalny przewodnik w tym dokumencie: how-to-call-aim-c-code-from-swift

Oto odpowiednia część:

Aby zaimportować zestaw plików Objective-C do kodu Swift w ramach tego samego celu aplikacji, polegasz na pliku nagłówkowym mostkującym Objective-C, aby udostępnić te pliki Swiftowi . Xcode oferuje utworzenie tego nagłówka po dodaniu pliku Swift do istniejącej aplikacji Objective-C lub pliku Objective-C do istniejącej aplikacji Swift.

Jeśli zaakceptujesz, Xcode tworzy plik nagłówka pomostowego wraz z plikiem, który tworzysz, i nadaje mu nazwę, używając nazwy modułu produktu, a następnie „-Bridging-Header.h”. Możesz także samodzielnie utworzyć mostkujący nagłówek, wybierając opcję Plik> Nowy> Plik> [system operacyjny]> Źródło> Plik nagłówka

Edytuj nagłówek pomostowy, aby udostępnić kod Objective-C kodowi Swift:

  1. W nagłówku pomostowym Cel-C zaimportuj każdy nagłówek Cel-C, który chcesz udostępnić Swift .
  2. W Ustawieniach kompilacji, w Swift Compiler - Generowanie kodu, upewnij się, że ustawienie kompilacji Nagłówek mostku celu C ma ścieżkę do pliku nagłówka mostka. Ścieżka powinna być względna do twojego projektu, podobnie jak ścieżka Info.plist jest określona w Ustawieniach kompilacji. W większości przypadków nie trzeba modyfikować tego ustawienia.

Wszelkie publiczne nagłówki Celu C wymienione w nagłówku pomostowym są widoczne dla Swift.

Tibin Thomas
źródło
0

Dwukierunkowe podejście do użycia celu-c celu-c

1

  1. Utwórz plik bridge-header.h w Xcode Project
  2. zaimportuj plik .h do pliku nagłówka pomostu
  3. Ustaw ścieżkę nagłówka mostka w Ustawieniach kompilacji.
  4. Oczyść projekt

2)

  1. Utwórz pliki celu c w projekcie (automatycznie ustawia dla Ciebie ścieżkę w Ustawieniach kompilacji)
  2. zaimportuj plik .h do pliku nagłówka pomostu

Teraz dobrze iść Dzięki

Sanjay Mali
źródło