Вызов функции Swift из класса Objective-C

84

У меня есть старый проект Objective-C, и я хочу вызвать новую функцию и объект Swift, я создал файл " <ProjectName>-Bridging-Header.h" и " <ProjectName>-Swift.h"

Мне было легко вызвать функцию из Swift в Objective-C, но у меня проблема с обратным.

Итак, я создал простой класс «System.Swift».

import Foundation

@objc class System : NSObject {

    @objc func printSome() {
        println("Print line System");
    }
    
}

Теперь я должен попытаться следовать документации здесь и внутри <...>-Swift.hфайла, который я написал

@class System;

@interface System : NSObject

-(void)printSome;

@end

и я импортировал его в свой класс Objective-C. В этот момент внутри моего класса Objective C (в настоящее время UIViewController) моего кода Objective-C я пытаюсь вызвать метод printSome:

- (void)viewDidLoad
{
    [super viewDidLoad];
    System * sis = [[System alloc] init];
    [sis printSome];
    //any additional setup after loading the view from its nib.
}

теперь у меня следующая ошибка:

Неопределенные символы для архитектуры i386: « OBJC_CLASS $ _System», ссылка на которую: objc-class-ref в «ObjectiveC_Class_That_Call_Swift_Object» .o ld: символ (ы) не найден для архитектуры i386 clang: error: команда компоновщика завершилась неудачно с кодом выхода 1 (используйте -v, чтобы увидеть вызов)

Элореден
источник
У вас ошибка компоновщика. Это: (1) Xcode использует имя вашего модуля продукта, а не ваше целевое имя, при именовании заголовка моста Objective-C и сгенерированного заголовка для вашего кода Swift, или (2) обязательно импортируйте заголовки Objective-C для этих типы до импорта созданного Swift заголовка в файл Objective-C .m, из которого вы хотите получить доступ к коду Swift? У вас есть: #import «ProductModuleName-Swift.h» в вашем коде Objective-C?
Petert 06
Да, я прочитал документацию, и имя «ProductModelName» правильное ... Есть ошибка, из-за которой в настройках сборки модель продукта не была установлена ​​... я даже установил ее ...
Элореден
@petert, можешь лучше объяснить второй пункт? Я писал все, что делал ...
Элореден
Проблема решена, я добавил новый файл .h в свой проект с вызовом <ProductModelName> -Swift.h, но в этом нет необходимости, потому что компилятор просто создает этот объект, даже если я его не вижу. Я удалил новый файл, который я создал, и теперь все работает отлично. Tnx petert
Eloreden 06
Вы можете ответить на свои вопросы - это может помочь другим.
Petert 06

Ответы:

51

Проблема решена, я ранее создал и включил новый .hфайл в свой класс Objective-C с именем, <ProductModuleName>-Swift.hно, как я обнаружил позже, в этом шаге нет необходимости, поскольку компилятор создает необходимый файл невидимым.

Просто включите <ProductModuleName>-Swift.hв свой класс, и он должен работать.

Элореден
источник
3
как насчет функций с параметрами?
Arnlee Vizcayno
3
Я не могу получить доступ к функциям Swift с параметрами и возвращаемым значением, а также не могу получить доступ к функциям Swift без параметров и без возвращаемого значения. Не знаю почему. Мой класс Swift - это NSObject, я импортировал фреймворк Foundation, класс и функции имеют @objcпрефикс. -Swift.hБыла создана автоматически. У меня головная боль от того, что я могу вызывать сам класс, но не любую функцию внутри него. Кто-нибудь знает почему?
David Gölzhäuser
4
хороший пример на ericasadun.com/2014/08/21/…
Paul Beusterien
2
Это <productModuleName>-.Swift.h(нет model).
SwiftArchitect
2
Если ваше имя продукта имеет какие - либо пробелы в нем, замените их на подчеркивания, например: #import "My_Project-Swift.h".
EricRobertBrewer
41

это странно но это сработает

1) Add @objc  to  Swift class

2) Add in .m 
    #import "(ProjectName)-Swift.h"

3) Call from .h
    @class SwiftClass;

4)On SwiftClass 
   click "Command" + Left Click (Apple Documantation)

5) To see "-Swift.h" -> click "Command" + Left Click

Приложение сгенерирует интерфейс для этого класса в -Swift.h

Пример: SWIFT_CLASS ("_ TtC10Project17220PLHelper") @interface PLHelper

  • (void) notifyForDownloading: (NSDictionary *) userInfo;
  • (тип экземпляра) init OBJC_DESIGNATED_INITIALIZER; @конец
Светлана
источник
Вы также можете переопределить имя Obj-C вашего класса Swift, используя@objc (MyClassName)
nielsbot
12
Для всех, кто может совершить такую ​​же глупую ошибку, как я. На шаге 2, убедитесь , что вы используете (ProjectName)-Swift.h, НЕ (ClassName)-Swift.h !
Hlung
спасибо @Svitlana, невероятно, это сработало !!! Но мне приходится многократно повторять эти шаги, включая перемещение моих добавленных методов в другие места в классе.
Скофилд Тран,
1
3) @class SwiftClassName;спас меня
Мазен
33

Предположим, у нас есть имя проекта «MyFirstProjectOnSwift», имя быстрого класса «mySwiftClass» и класс objectiveC «MyObjectiveCLass».

Следующие шаги: -

  1. Добавьте #import "MyFirstProjectOnSwift-Swift.h" в "MyObjectiveCLass.m"

  2. Добавьте @class mySwiftClass в MyObjectiveCLass.h;

  3. Затем в MyObjectiveCLass.m

    mySwiftClass * myClass = [mySwiftClass новый]; {Вызовите подобное в любом методе, где бы вы ни хотели вызвать быстрый метод.}

  4. [myClass methodName];

Анубхав Гири
источник
2
mySwiftClass * myClass = [mySwiftClass new] у меня не работает >>>>>
Хари Нараянан
@HariNarayanan Этого не должно быть, подумайте, очистите производные данные и заново откройте свой проект.
Anubhav Giri
12

Проверьте файл -Swift.h, который импортирует ваш .m файл в объект-C:

#import <YourProjectName-Swift.h>

Щелкните эту строку и щелкните левой кнопкой мыши - Перейти к определению.

Этот файл следует включать автоматически, а не вручную.

Дариус Миляускас
источник
2

Если вы все еще не видите свой класс даже после импорта <ProductModuleName>-Swift.h.

Убедитесь, что ваш класс является подклассом собственного класса (например UIViewController) или, по крайней мере, если это просто служебный класс, сделайте его подклассом NSObject. Ваш класс должен теперь отображаться.

Брайан П.
источник
2

Небольшой дополнительный совет для тех, кто наткнулся на этот пост и для тех, у кого другие ответы не работают: вам также может потребоваться объявить свой класс Swift «общедоступным».

Пример:

@objc public class MySwiftClass: NSObject {

Kqtr
источник
0

Рекомендуемый способ выполнения кода Swift из Objective-C в проектах, которые переносятся с Obj-C на Swift, использует шаблон Bridge / Proxy.

  1. Реализуйте мост.

import Foundation

@objc class AnalyticsPropertyBridge: NSObject {

private var analytics: AnalyticsManager = AnalyticsManager()

@objc func refreshProperties() {

    self.analytics.set(AnalyticsProperty.clientType)
}

}

  1. Включите вызывающий модуль objC в зонтичный файл (Bridging-Header):

#import "CallerModule.h"

  1. Наконец, в файле .m вызывающего абонента две проблемы:

3.a Импортировать зонтичный файл:

#import "MyProject-Swift.h"

3.b Вызовите мост.

[[AnalyticsPropertyBridge new] refreshProperties];

Преимущества: ваш быстрый код не испачкается с @objc, потому что код вызывается из Objc. Со временем ObjC будет уменьшаться в вашем проекте, и, наконец, невеста будет удалена.

Хавьер Калатрава Ллаверия
источник
-1

Хорошая статья, если у кого-то все еще есть проблемы.

Настройка совместимости Swift и Objective-C

  1. В этой статье подробно обсуждается, как импортировать файлы Swift в ObjC, а также файлы Objc в Swift.
  2. Он также решает проблему, с которой обычно сталкиваются, когда в имени проекта есть пробел.
  3. Также обсуждается флаг «Название модуля продукта».
Трезубец
источник
Хотя теоретически это может дать ответ на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки.
Arghya Sadhu