Как в Swift вызывать код Objective-C?
Apple упомянула, что они могут сосуществовать в одном приложении, но означает ли это, что можно технически повторно использовать старые классы, созданные в Objective-C, при создании новых классов в Swift?
Как в Swift вызывать код Objective-C?
Apple упомянула, что они могут сосуществовать в одном приложении, но означает ли это, что можно технически повторно использовать старые классы, созданные в Objective-C, при создании новых классов в Swift?
** Если у вас есть существующий класс, который вы хотели бы использовать, выполните шаг 2, а затем перейдите к шагу 5. (В некоторых случаях мне пришлось добавить явный #import <Foundation/Foundation.h
в более старый файл Objective-C.) **
Добавьте файл .m
к своему классу и назовите его CustomObject.m
.
При добавлении файла .m
вы, скорее всего, получите приглашение, которое выглядит следующим образом:
Нажмите ДА !
Если вы не увидели подсказку или случайно удалили заголовок моста, добавьте новый файл .h
в свой проект и назовите его <#YourProjectName#>-Bridging-Header.h
.
В некоторых ситуациях, особенно при работе со средами Objective C, вы не добавляете класс Objective C явно, и XCode не может найти компоновщик. В этом случае создайте файл .h
именем, указанным выше, а затем убедитесь, что вы связали его путь в настройках целевого проекта следующим образом:
Заметка
Рекомендуется связывать ваш проект с помощью макроса $(SRCROOT)
чтобы при перемещении проекта или работе над ним с другими с помощью удаленного репозитория он все еще работал. $(SRCROOT)
можно рассматривать как каталог, содержащий ваш файл .xcodeproj. Это может выглядеть так:
$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h
Добавьте другой файл .h
и назовите его CustomObject.h
.
В 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
В YourProject-Bridging-Header.h
:
#import "CustomObject.h"
В SomeSwiftFile.swift
:
var instanceOfCustomObject: CustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
println(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()
Нет необходимости явно импортировать; это то, для чего предназначен соединительный заголовок.
Добавьте файл .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
}
}
В SomeRandomClass.m
:
#import "<#YourProjectName#>-Swift.h"
Файл: <#YourProjectName#>-Swift.h
уже должен быть автоматически создан в вашем проекте, даже если вы его не видите.
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, ответ будет обновлен соответствующим образом.
См. руководство Apple в Использование Swift с Cocoa и Objective-C. В этом руководстве описывается использование Objective-C и кода C из Swift и наоборот, а также рекомендации по преобразованию проекта или его смешению и соответствия Objective-C/C и деталям Swift в существующем проекте.
Компилятор автоматически генерирует синтаксис Swift для вызова функций C и методов Objective-C. Как видно из документации, этот Objective-C:
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
превращается в этот код Swift:
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)
Xcode также выполняет этот перевод "на лету" - вы можете использовать "Открыть быстро" при редактировании файла Swift и ввести имя класса Objective-C, и оно перенесет вас в версию заголовка класса Swift. (Вы также можете получить это, нажав cmd на символ API в файле Swift.) И вся справочная документация API в iOS 8 и OS X v10.10 (Yosemite) библиотеки разработчиков видны как в формах Objective-C, так и в Swift (например, UIView
).
Ниже приведены пошаговые инструкции по использованию кода Objective C (в данном случае, среды, предоставленной сторонней организацией) в проекте Swift:
Простыми шагами:
Появится приглашение, а затем нажмите "ОК". Если оно не появится, мы создадим его вручную, как показано ниже... Создайте один файл заголовка из источника iOS и присвойте ему имя ProjectName-Bridging-Header (пример: Test -Bridging-Header), а затем перейдите к настройке сборки в коде компилятора Swift → Мост Objective-C добавьте имя моста Objective-C.. (Test/Test-Bridging-Header.h). Да, это завершено.
При желании удалите добавленный вами файл Objective-C (с именем "что-нибудь" на изображении GIF выше). Вам это больше не нужно.
Откройте файл заголовка моста - имя файла имеет вид [YourProject] -Bridging-Header.h. Это включает предоставленный Xcode комментарий. Добавьте строку кода для файла Objective-C, который вы хотите включить в, например стороннюю платформу. Например, чтобы добавить Mixpanel в ваш проект, вам нужно добавить следующую строку кода в заголовочный файл моста:
#import "Mixpanel.h"
Теперь в любом файле 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 - код" поколение".
Вы можете прочитать хороший пост 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.
Я написал простой проект Xcode 6, который показывает, как смешивать С++, Objective-C и код Swift:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
В частности, пример вызывает функцию Objective-C и С++ из Swift.
Ключом является создание общего заголовка Project-Bridging-Header.h и размещение заголовков Objective-C.
Пожалуйста, загрузите проект в качестве полного примера.
Цитата из documentation:
Любая инфраструктура Objective-C (или библиотека C), доступная как модуль могут быть импортированы непосредственно в Swift. Сюда входят все Objective-C системные рамки, такие как Foundation, UIKit и SpriteKit, а также общие библиотеки C, поставляемые с системой. Для Например, чтобы импортировать Foundation, просто добавьте этот оператор импорта в вверху файла Swift, в котором вы работаете:
import Foundation
Этот импорт делает все базовые API-интерфейсы, включая NSDate, NSURL, NSMutableData и все их методы, свойства и категорий, доступных непосредственно в Swift.
Я очень благодарен за ответ @Logan. Он очень помогает создавать файл моста и настройки.
Но после выполнения всех этих шагов я все еще не получаю класс Objective-C в Swift.
Я использовал библиотеку cocoapods
и интегрировал ее в свой проект. Что такое pod "pop"
.
Поэтому, если вы используете объекты Objective-C в Swift, тогда может возникнуть вероятность того, что вы не сможете получить или import
классы в Swift.
Простая вещь, которую вы должны сделать, это:
<YOUR-PROJECT>-Bridging-Header
file и#import <ObjC_Framework>
на @import ObjC_Framework
Например: (поп-библиотека)
замещать
#import <pop/POP.h>
с
@import pop;
Использовать clang import
когда #import
не работает.
Просто обратите внимание на тех, кто пытается добавить библиотеку Objective-C в Swift: вы должны добавить -ObjC в настройках сборки → Связывание → Другие флаги компоновщика.
После того, как вы создали заголовок Bridging, перейдите в Build Setting => Search для "Objective-C Bridging Header".
Чуть ниже вы найдете файл "" Имя заголовка сгенерированного интерфейса Objective-C ".
Импортируйте этот файл в свой контроллер представления.
Пример: в моем случае: "Dauble-Swift.h"
Нажмите меню "Новый файл" и выберите язык выбора файла Цель. В это время он автоматически генерирует файл Objective-C Bridging Header ", который используется для определения некоторого имени класса.
"Objective-C Мостовой заголовок" в разделе "Быстрый компилятор - генерация кода".
Я добавил проект на github, который включает небольшой образец для вызова объектного кода c из swift.
Любая инфраструктура Objective-C (или библиотека C), доступная как модуль, может быть импортирована непосредственно в Swift. Сюда входят все системные рамки Objective-C, такие как Foundation, UIKit и SpriteKit, а также общие библиотеки C, поставляемые с системой. Например, чтобы импортировать Foundation, просто добавьте этот оператор импорта в начало файла Swift, в котором вы работаете:
import Foundation
Этот импорт включает все базовые API-интерфейсы, включая NSDate, NSURL, NSMutableData и все их методы, свойства и категории, непосредственно доступные в Swift.
Я взял это из документации Apple.
В проекте 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
.
Step_05: Будет создан соответствующий файл с именем:
Objc-Bridging-Header.h
.
Шаг_06: Теперь вам нужно установить путь к файлу Bridge в заголовке моста. В Project Navigator нажмите проект с именем objc
а затем выберите:
Build Settings
> Objective-C Bridging Header
> Objc-Bridging-Header.h
.
Step_07: Перетащите свой Objc-Bridging-Header.h
в это поле, чтобы создать путь к файлу.
Step_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)
}
Добавить заголовок Objective C .h
и реализацию .m
Добавьте файлы <FileName>.m
и <FileName>.h
в свой проект
Добавить заголовок моста
При добавлении файла .m нажмите "Да" на приглашении Would you like to configure an Objective-C bridging header
Добавить класс в заголовок моста
В YourProject-Bridging-Header.h
добавьте строку #import "<FileName>.h"
<FileName>.swift
, который расширяет NSObject
, в ваш проект#import "<#YourProjectName#>-Swift.h"
в файл Objective-CПодробнее здесь
Первый шаг: -
Если вы добавляете объективный файл c, где ваш проект был создан на языке быстрой передачи, вы получаете такой вариант, как ниже
создать мостовой файл заголовка отсюда или добавить новое имя файла заголовка моста как
Имя_проекта (название проекта) -Bridging-Header.h
импортировать Objective C ".h" файл в заголовке, например,
#ifndef Test_Bridging_Header_h
#define Test_Bridging_Header_h
#import "TestViewController.h" /*Objective C file*/
#endif /* Test_Bridging_Header_h */
Второй шаг: -
Связывание заголовка моста с вашей целью
Цель проекта → Настройка сборки. Обновите эти свойства.
"Определяет модуль": ДА.
"Всегда вставлять быстрые стандартные библиотеки": ДА.
"Установить Objective-C Заголовок совместимости": ДА.
Двухсторонний подход к использованию target-c target-c
1
2
Теперь хорошо идти Спасибо
В этом документе 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:
Все общедоступные заголовки Objective-C, перечисленные в заголовке моста, видны Swift.
Ответ Logans работает нормально, за исключением последнего 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
}
}