Как мне вызвать код Objective-C из Swift?

974

В Swift, как можно назвать код Objective-C?

Apple упомянула, что они могут сосуществовать в одном приложении, но означает ли это, что можно технически повторно использовать старые классы, созданные в Objective-C, при создании новых классов в Swift?

Дэвид Малдер
источник
13
См. Руководство Apple по использованию Swift с какао и Objective-C .
Рикстер
10
Интересно, что этот вопрос получает так много голосов и щедрости. Когда я впервые увидел это, я просто подумал: RTFM. На самом деле это не показывает никаких исследований, поскольку в настоящее время есть только два или три ресурса, которые официально документируют Swift, и один из них полностью посвящен именно этому (и связан с первым комментарием).
Аналоговый файл
6
@EvolGate: что именно отсутствует в Objective C, что мешает ему быть независимым от платформы языком? Язык и стандартные языковые библиотеки имеют открытый исходный код. Вы можете использовать Objective C для Windows, Os X, Linux, BSD, Solaris и для любой другой платформы, поддерживаемой GCC или LLVM. Вы можете легко перенести Objective C на любую платформу с приличным компилятором C, даже если она не поддерживается ни GCC, ни LLVM. Я не понимаю, как это может быть более независимым от платформы, чем это.
Аналоговый файл
2
@DavidMulder: нужен ли раздел «Разум»?
Франк

Ответы:

1395

Использование классов Objective C в Swift

Если у вас есть существующий класс, который вы хотите использовать, выполните Шаг 2, а затем перейдите к Шаг 5 . (В некоторых случаях мне пришлось добавить явное #import <Foundation/Foundation.hв более старый файл Objective-C.)

Шаг 1. Добавьте реализацию Objective-C - .m

Добавьте .mфайл в ваш класс и назовите его CustomObject.m.

Шаг 2: Добавьте заголовок моста

При добавлении .mфайла вы, скорее всего, получите приглашение, которое выглядит следующим образом:

Диалоговое окно в стиле листа MacOS из XCode, спрашивающее, хотите ли вы «настроить заголовок моста Objective C»

Нажмите Да !

Если вы не увидели подсказку или случайно удалили соединительный заголовок, добавьте новый .hфайл в свой проект и назовите его <#YourProjectName#>-Bridging-Header.h.

В некоторых ситуациях, особенно при работе со средами Objective C, вы не добавляете класс Objective C явно, и XCode не может найти компоновщик. В этом случае создайте свой .hфайл с именем, как указано выше, затем убедитесь, что вы связали его путь в настройках проекта вашей цели следующим образом:

Анимация, демонстрирующая вышеуказанный абзац

Замечания:

Рекомендуется связывать ваш проект с помощью $(SRCROOT)макроса, чтобы при перемещении проекта или работе над ним с другими с помощью удаленного репозитория он продолжал работать. $(SRCROOT)может рассматриваться как каталог, содержащий ваш файл .xcodeproj. Это может выглядеть так:

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

Шаг 3: Добавьте заголовок Objective C - .h

Добавьте другой .hфайл и назовите его CustomObject.h.

Шаг 4. Создайте свой класс Objective-C

В CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

В CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

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

@end

Шаг 5: добавьте класс в Bridging-Header

В YourProject-Bridging-Header.h:

#import "CustomObject.h"

Шаг 6: Используйте свой объект

В SomeSwiftFile.swift:

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

Нет необходимости явно импортировать; это то, для чего предназначен соединительный заголовок.

Использование Swift-классов в Objective-C

Шаг 1: Создайте новый класс Swift

Добавьте .swiftфайл в ваш проект и назовите его MySwiftObject.swift.

В 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)"
    }
}

Шаг 2. Импорт файлов Swift в класс ObjC

В SomeRandomClass.m:

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

Файл: <#YourProjectName#>-Swift.hуже должен автоматически создаваться в вашем проекте, даже если вы его не видите.

Шаг 3: Используйте свой класс

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

Ноты:

  1. Если завершение кода ведет себя не так, как вы ожидаете, попробуйте запустить быструю сборку, Rчтобы помочь Xcode найти часть кода Objective-C из контекста Swift и наоборот.

  2. Если вы добавляете .swiftфайл в более старый проект и получаете сообщение об ошибке dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, попробуйте полностью перезапустить XCode .

  3. Хотя изначально было возможно использовать чистые классы Swift (не потомки NSObject), которые видимы для Objective-C с помощью @objcпрефикса, это больше невозможно. Теперь, чтобы быть видимым в Objective-C, объект Swift должен быть либо классом, соответствующим NSObjectProtocol(самый простой способ сделать это наследовать от NSObject), либо быть enumпомеченным @objcс необработанным значением некоторого целочисленного типа, такого как Int. Вы можете просмотреть историю редактирования для примера использования кода Swift 1.x @objcбез этих ограничений.

логан
источник
5
Важно, что вам нужно аннотировать методы с помощью методов @objc или Swift, которые не будут видны из Objective-C.
Томаш Линхарт
29
Вы правы. Вам нужно только указать его, если вы не используете объекты Какао. Чтобы быть доступным и пригодным для использования в Objective-C, класс Swift должен быть потомком класса Objective-C или иметь пометку @objc.
Томаш Линхарт
2
@MarkusRautopuro - Получил это здесь: developer.apple.com/library/prerelease/ios/documentation/Swift/… "
Логан
2
См. Также: WWDC 2014, Сессия 406: Интеграция Swift с Objective-C
Стюарт М,
6
При импорте фреймворка Objective C в Swift убедитесь, что импортировали все фреймворки, от которых зависит фреймворк Obj C, в ваш проект (в Фазах сборки -> Связать двоичные файлы с библиотеками), а затем добавьте # import для них в заголовочный файл префикса, который необходимо добавить в проект в настройках сборки (в поле «Заголовок префикса»). Это включает в себя фреймворки, такие как UIKit и Foundation, даже если они уже используются в Swift. Это сбило меня с толку на несколько часов, и никто, кажется, не задокументировал эти шаги.
user1021430 20.11.14
121

См. Руководство Apple по использованию Swift с какао и Objective-C . В этом руководстве рассказывается, как использовать код Objective C и C из Swift и наоборот, и даются рекомендации по преобразованию проекта или смешиванию и сопоставлению частей Objective C / C и Swift в существующем проекте.

Компилятор автоматически генерирует синтаксис Swift для вызова функций C и методов Objective-C. Как видно из документации, эта Цель-C:

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

превращается в этот код Swift:

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

XCode также делает этот перевод на лету - вы можете использовать Open Quickly при редактировании файла Swift и ввести имя класса Objective-C, и это приведет вас к Swift-версии заголовка класса. (Вы также можете получить это, нажав cmd на символ API в файле Swift.) И вся справочная документация по API в библиотеках для разработчиков iOS 8 и OS X v10.10 (Yosemite) видна как в Objective-C, так и в Swift. формы (например UIView).

rickster
источник
3
Прямая ссылка на документацию Apple о том, как интегрировать Swift в существующий проект: developer.apple.com/library/prerelease/ios/documentation/Swift/…
skywinder
Если вы заинтересованы о том, почему нужны заголовочные файлы и как она используется во время стадии компоновки, то убедитесь , что вы читаете эту Manual Swift: Понимание Swift / Objective-C Сложение Pipeline
Honey
62

Ниже приведены пошаговые инструкции по использованию кода Objective-C (в данном случае, среды, предоставленной сторонней организацией) в проекте Swift:

  1. Добавьте любой файл Objective-C в ваш проект Swift , выбрав Файл -> Новый -> Новый файл -> Файл Objective-C. После сохранения Xcode спросит, хотите ли вы добавить соединительный заголовок . Выберите « Да ». (источник: derrrick.com )Gif: добавление пустого файла в проект и создание заголовка моста

В простых шагах:

  1. Появится приглашение, а затем нажмите «ОК». Если оно не появится, мы создадим его вручную, как показано ниже ... Создайте один файл заголовка из источника iOS и присвойте ему имя ProjectName-Bridging-Header (пример: Test -Bridging-Header), а затем перейдите к настройке сборки в коде компилятора Swift -> Мост Objective-C добавьте имя моста Objective-C .. (Test / Test-Bridging-Header.h). Да, это завершено.

  2. При желании удалите добавленный вами файл Objective-C (с именем «что-нибудь» на изображении GIF выше). Вам это больше не нужно.

  3. Откройте файл заголовка моста - имя файла имеет вид [YourProject] -Bridging-Header.h . Это включает предоставленный Xcode комментарий. Добавьте строку кода для файла Objective-C, который вы хотите включить , например стороннюю платформу. Например, чтобы добавить Mixpanel в ваш проект, вам нужно добавить следующую строку кода в заголовочный файл моста:

    #import "Mixpanel.h"
  4. Теперь в любом файле Swift вы можете использовать существующий код Objective-C в синтаксисе Swift (в случае этого примера, и вы можете вызывать методы Mixpanel SDK и т. Д.). Вам необходимо ознакомиться с тем, как Xcode переводит Objective-C в Swift. Руководство Apple - это краткое руководство . Или посмотрите этот ответ для неполного резюме.

Пример для Mixpanel:

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

Это оно!

Примечание. Если вы удалите файл заголовка моста из своего проекта , обязательно зайдите в настройки сборки и удалите значение для « Objective-C Bridging Header » в «Swift Compiler - Generation Code».

derrrick
источник
39

Вы можете прочитать хороший пост Swift & Cocoapods . По сути, нам нужно создать файл заголовка моста и поместить туда все заголовки Objective-C. И тогда нам нужно сослаться на это из наших настроек сборки. После этого мы можем использовать код 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)
  })

Также ознакомьтесь с документом Apple « Использование Swift с какао и Objective-C» .

Джейк Лин
источник
25

Я написал простой проект для Xcode 6, который показывает, как смешивать код C ++, Objective-C и Swift:

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

В частности, в примере вызывается функция Objective-C и C ++ из Swift .

Ключом является создание общего заголовка Project-Bridging-Header.h и размещение там заголовков Objective-C.

Пожалуйста, скачайте проект как полный пример.

Джан Луиджи Ромита
источник
24

Я хотел бы добавить еще одну вещь:

Я очень благодарен за ответ @ Logan. Это очень помогает для создания файла моста и настроек.

Но после выполнения всех этих шагов я все еще не получаю класс Objective-C в Swift.

Я использовал cocoapodsбиблиотеку и интегрировал ее в свой проект. Который есть pod "pop".

Так что, если вы используете модули Objective-C в Swift, то есть вероятность, что вы не сможете получить importэти классы в Swift.

Простая вещь, которую вы должны сделать, это:

  1. Перейти к <YOUR-PROJECT>-Bridging-Headerфайлу и
  2. Заменить заявление #import <ObjC_Framework>на@import ObjC_Framework

Например: (поп-библиотека)

замещать

#import <pop/POP.h>

с

@import pop;

Используйте, clang importкогда #importне работает.

Kampai
источник
Используйте импорт clang, когда #import не работает. что? Разве не сказали, что мы должны использовать @import ?!
Мед
22

Цитата из документации :

Любая среда Objective-C (или библиотека C), доступная в виде модуля, может быть импортирована непосредственно в Swift. Это включает в себя все системные платформы Objective-C, такие как Foundation, UIKit и SpriteKit, а также общие библиотеки C, поставляемые с системой. Например, чтобы импортировать Foundation, просто добавьте этот оператор импорта в начало файла Swift, в котором вы работаете:

import Foundation

Этот импорт делает все API-интерфейсы Foundation, включая NSDate, NSURL, NSMutableData и все их методы, свойства и категории, непосредственно доступными в Swift.

Герго Эрдоси
источник
12

Просто примечание для тех, кто пытается добавить библиотеку Objective-C в Swift: Вы должны добавить -ObjC в Настройки сборки -> Связывание -> Другие флаги компоновщика .

david72
источник
Почему? Пожалуйста, добавьте информацию о том, что делает этот флаг и почему он должен быть добавлен.
Йохан Карлссон
9

После того, как вы создали заголовок Bridging, перейдите в Build Setting => Search для «Objective-C Bridging Header».

Чуть ниже вы найдете файл "" Имя заголовка сгенерированного интерфейса Objective-C ".

Импортируйте этот файл в свой контроллер представления.

Пример: в моем случае: "Dauble-Swift.h"

Описание изображения eEter здесь

Авижит Нагаре
источник
5

Нажмите на меню « Новый файл» и выберите файл, выберите язык. В это время он автоматически генерирует файл "Objective-C Bridging Header", который используется для определения некоторого имени класса.

«Заголовок моста Objective-C» в разделе «Компилятор Swift - Генерация кода».

Йогеш шелке
источник
3
  1. Создайте .h файл из NewFile -> Source -> header file
  2. Затем сохраните имя файла Your_Target_Name-Bridging-Header.h Люди, получившие здесь распространенную ошибку, берут имя своего проекта, но это должно быть имя цели проекта, если в случае, когда оба они различны, обычно они одинаковы.
  3. Затем в настройках сборки найдите флаг заголовка моста Objective-C и введите адрес вновь созданного файла моста, вы можете сделать это, щелкнув правой кнопкой мыши файл -> показать в Finder -> перетащить файл в текстовую область, после чего адрес будет быть заселённым
  4. Использование #import Your_Objective-C_file.h
  5. В файле swift вы можете получить доступ к файлу ObjC, но только на языке swift.
Ниша
источник
3

введите описание изображения здесьЯ добавил проект на GitHub, который включает в себя небольшой пример для вызова объективного кода C из Swift.

Вызовите ObjectiveC класс из Swift

CrazyPro007
источник
ПРИМЕЧАНИЕ: - Когда вы создаете класс Objc в проекте swift, xcode запрашивает автоматическое соединение класса. Не беспокойтесь :)
CrazyPro007
3

В проекте Swift 4.2.1 в Xcode 10.1 вы можете легко добавить файл Objective-C. Выполните следующие действия, чтобы связать файл Objective-C с проектом Swift.

Step_01: Создайте новый проект Xcode, используя язык Swift:

File> New> Project> objc.

Step_02: В проект Swift добавьте новый файл Objective-C:

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

Step_03: Если вы добавляете новый файл Objective-C в проект Swift в первый раз, Xcode спросит вас:

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

введите описание изображения здесь

Step_04: выберите опцию:

Create Bridging Header,

Шаг_05: Будет создан соответствующий файл с именем:

Objc-Bridging-Header.h,

введите описание изображения здесь

Шаг_06: Теперь вам нужно настроить путь к файлу моста в заголовке моста. В Project Navigator нажмите на проект с именем objcи затем выберите:

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

Шаг_07: Перетащите курсор Objc-Bridging-Header.hв это поле, чтобы сгенерировать путь к файлу.

введите описание изображения здесь

Шаг_08: Откройте ваш Objc-Bridging-Header.hфайл и импортируйте файл Objective-C, который вы хотите использовать в вашем файле Swift.

#import "SpecialObjcFile.m"

Вот содержание SpecialObjcFile.m:

#import <Foundation/Foundation.h>

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

Step_09: Теперь в вашем Swift-файле вы можете использовать класс Objective-C:

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

введите описание изображения здесь введите описание изображения здесь

Энди
источник
1

Ответ Logans работает нормально, за исключением последнего, Swift 5он дает ошибку компилятора. Вот исправление для людей, которые работают над Swift 5.

Swift 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
    }
}
Саззад Хисейн Хан
источник
1

Свифт потребитель, производитель Objective-C

  1. Добавьте заголовок .hи .mфайлы реализации - файл класса какао (Objective-C),
    напримерMyFileName

  2. настроить заголовок моста
    Когда вы видите Would you like to configure an Objective-C bridging headerнажмите - Да

    • <target_name>-Bridging-Header.h будет сгенерирован автоматически
    • Настройки сборки -> заголовок моста Objective-C
  3. Добавить класс в Bridging-Header
    In <target_name>-Bridging-Header.hдобавить строку#import "<MyFileName>.h"

PS Если вам нужно добавить существующие файлы Objective-C в проект Swift, добавьте Bridging-Header.hзаранее

Objective-C потребитель, производитель Swift

  1. Добавить <MyFileName>.swiftи расширяетNSObject

  2. Импорт файлов Swift в класс ObjC
    Добавьте #import "<#YourProjectName#>-Swift.h"в свой файл Objective-C

  3. Отметить общедоступный код Swift [@objc and @objcMembers]

yoAlex5
источник
0

В этом документе Apple предоставила официальное руководство: как-звонить-цель-c-code-from-swift

Вот соответствующая часть:

Чтобы импортировать набор файлов Objective C в код Swift в пределах одной и той же цели приложения, вы полагаетесь на файл заголовка моста Objective C, чтобы открыть эти файлы для Swift . Xcode предлагает создать этот заголовок, когда вы добавляете файл Swift в существующее приложение Objective C или файл Objective C в существующее приложение Swift.

Если вы принимаете, Xcode создает файл заголовка моста вместе с файлом, который вы создали, и присваивает ему имя, используя имя модуля вашего продукта, за которым следует «-Bridging-Header.h». Кроме того, вы можете создать мостовой заголовок самостоятельно, выбрав «Файл»> «Создать»> «Файл»> [операционная система]> «Источник»> «Заголовочный файл».

Отредактируйте соединительный заголовок, чтобы представить ваш код Objective-C вашему коду Swift:

  1. В заголовке моста Objective C импортируйте каждый заголовок Objective C, который вы хотите показать в Swift .
  2. В настройках сборки в Swift Compiler - Generation Code убедитесь, что параметр сборки Objective-C Bridging Header имеет путь к файлу заголовка моста. Путь должен быть относительно вашего проекта, аналогично тому, как ваш путь Info.plist указан в настройках сборки. В большинстве случаев вам не нужно изменять этот параметр.

Все общедоступные заголовки Objective-C, перечисленные в заголовке моста, видны Swift.

Тибин Томас
источник
0

Двухсторонний подход к использованию target-c target-c

1

  1. Создайте файл bridge-header.h в проекте Xcode
  2. импортировать файл .h в файл заголовка моста
  3. Установить путь моста-заголовка в настройках сборки.
  4. Очистить проект

2

  1. Создайте файлы target-c в проекте (он автоматически устанавливает путь в настройках сборки для вас)
  2. импортировать файл .h в файл заголовка моста

Теперь хорошо идти Спасибо

Санджай Мали
источник