it-swarm.com.ru

Как вызвать код Objective-C из Swift

На новом языке Swift от Apple, как можно назвать код Objective-C?

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

Рассуждение

Objective-C является независимым от платформы языком, тогда как Swift зависит от платформы. Поэтому написание не зависящего от платформы кода (библиотек бизнес-логики) в Swift было бы неразумно. Тем не менее, написание платформо-зависимого кода в нем (например, связанный с интерфейсом) вполне подойдет. Не сказать, что это была бы хорошая идея, однако это определенно интерес.

904
David Mulder

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

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

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

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

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

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

Enter image description here

Нажмите ДА !

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

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

Enter image description here

Заметка

Рекомендуется связывать ваш проект с помощью макроса $(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 = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
println(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

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

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

Шаг 1. Создание нового класса Swift

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

В MySwiftObject.Swift:

import Foundation

class MySwiftObject : NSObject {

    var someProperty: AnyObject = "Some Initializer Val"

    init() {}

    func someFunction(someArg:AnyObject) -> String {
        var returnVal = "You sent me \(someArg)"
        return returnVal
    }   
}

Шаг 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);

// original
NSString * retString = [myOb someFunction:@"Arg"];
// xcode10 expands the external arg here
NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];|

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

Замечания:

1. CodeCompletion вел себя не так точно, как хотелось бы. В моей системе выполнение быстрой сборки с помощью "cmd + r", казалось, помогло Swift найти некоторый код Objective-C и наоборот.

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

3. Хотя изначально было возможно использовать чистые классы Swift в Objective-C с помощью префикса @objc, после Swift 2.0 это больше невозможно. Смотрите историю изменений для оригинального объяснения. Если эта функция будет включена в будущих версиях Swift, ответ будет обновлен соответствующим образом.

1311
Logan

См. Руководство 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 ).

115
rickster

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

  1. Добавьте любой файл Objective-C в проект Swift , выбрав Файл -> Новый -> Новый файл -> Файл Objective-C , После сохранения Xcode спросит, хотите ли вы добавить соединительный заголовок . Выберите " Да ". Gif: добавление пустого файла в проект и создание заголовка моста http://www.derrrick.com/stackoverflow/1-empty-file.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 "в разделе" Компилятор Swift - Генерация кода ".

57
derrrick

Вы можете прочитать хороший пост 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 с Cocoa и Objective-C.

36
Jake Lin

Я написал простой проект 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.

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

23
Gian Luigi Romita

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

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

import Foundation

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

20
Gergo Erdosi

Еще одна вещь, которую я хотел бы добавить здесь:

Я очень благодарен за ответ @ 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 не работает.

19
Kampai

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

10
david72

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

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

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

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

eEter image description here

8
Avijit Nagare

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

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

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

enter image description here Я добавил проект на github, включающий небольшой пример для вызова кода Objective C из Swift.

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

3
CrazyPro007

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

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

File> New> Project> objc.

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

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

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

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

enter image description here

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

Create Bridging Header.

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

Objc-Bridging-Header.h.

enter image description here

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

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

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

enter image description here

Шаг_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)
}

enter image description hereenter image description here

1
ARGeo

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

1

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

2

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

Теперь можно идтиСпасибо

0
Sanjay Mali

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
Tibin Thomas

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
    }
}
0
Sazzad Hissain Khan