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

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

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

Доводы

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

15 ответов


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

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

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

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

Шаг 2: Добавить Заголовок Моста

при добавлении .m file, вы, вероятно, будете поражены подсказкой, которая выглядит так:

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: Создайте свою цель-Класс 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: используйте свой объект

In 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);
NSString * retString = [myOb someFunction:@"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, ответ будет обновлен соответствующим образом.


см. руководство Apple по использование Swift с какао и Objective-C. Это руководство охватывает использование кода Objective-C и C из Swift и наоборот и содержит рекомендации по преобразованию проекта или смешиванию и сопоставлению частей Objective-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 быстро при редактировании Swift-файла и ввести имя класса Objective-C, и это приведет вас к Swift-ified версии заголовка класса. (Вы также можете получить это, нажав cmd на символ API в Swift-файле.) И вся справочная документация по API в iOS 8 и OS X v10.10 (Иосемити) библиотеки разработчиков отображаются как в формах Objective-C, так и в Swift (например UIView).


вот пошаговые инструкции по использованию кода 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 bridge add Objective-C bridge name ..(Test / Test-Bridging-Header.ч.) Да, это все.

  2. при необходимости удалите файл Objective-C, который вы добавили (с именем "что-нибудь" в изображении GIF выше). Она тебе больше не нужна.

  3. откройте файл заголовка моста -- имя файла имеет вид [YourProject] - Мост-Заголовок.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
}

вот именно!

Примечание: если вы удалите файл заголовка моста из своего проекта обязательно зайдите в настройки сборки и удалить значения "Цель-C Мостовой Заголовок "в разделе" Swift компилятор-генерация кода".


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


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

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


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

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

import Foundation

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


еще одна вещь я хотел бы добавить здесь:

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

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

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

поэтому, если вы используете Objective-C pods в Swift, то может быть шанс, что вы не сможете получить или import в классы в Swift.

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

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

например: (Pop library)

заменить

#import <pop/POP.h>

С

@import pop;

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


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


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

чуть ниже вы найдете файл" "Objective-C Generated Interface Header Name".

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

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

eEter image description here


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

"Objective-C Bridging Header" в разделе "Swift компилятор-генерация кода".


  1. создать .H файл из NewFile - > источник - > файл заголовка
  2. затем сохраните имя файла Your_Target_Name-Bridging-Заголовок.h люди здесь получают общую ошибку, принимая имя своего проекта, но это должно быть имя цели проекта, если в случае, если оба они разные, как правило, они одинаковы.
  3. затем в настройках сборки найдите Цель-C Мостовой Заголовок флаг и поставить адрес вашего вновь созданного файла моста, вы можете сделать щелкните правой кнопкой мыши файл - > показать в finder - > перетащите файл в текстовую область, затем адрес будет заполнен.
  4. использование #import Your_Objective-C_file.h
  5. в файле swift вы можете получить доступ к файлу ObjC, но только на языке swift.

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

import Foundation

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

Я взял это из документации Apple.


двусторонний подход к использованию objective-C objective-C

1

1. Create bridge-header.h file in Xcode Project
2. import .h file in bridge-Header file
3. Set path of bridge-Header in Build settings. 
3. Clean the Project 

2

  1. Create objective-c files in project(it automatically set path in Build Settings for you )
  2. import .h file in bridge-Header file

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


enter image description hereя добавил проект на github, который включает небольшой образец для вызова кода objective c из swift.

вызов класса ObjectiveC из swift


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

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 project в первый раз, Xcode спрашивает вас:

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

enter image description here

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

Create Bridging Header.

Step_05: будет создан соответствующий файл с именем:

Objc-Bridging-Header.h.

enter image description here

Step_06: теперь вам нужно настроить путь к файлу моста в заголовке моста. В Навигаторе Проекта нажмите на проект с именем objc и выберите:

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

Step_07: перетащите свой Objc-Bridging-Header.h в это поле для создания пути к файлу.

enter image description here

Step_08: открыть свой Objc-Bridging-Header.h file и импортируйте файл 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 here enter image description here