Виклик функції 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: помилка: команда зв’язування не вдалася з кодом виходу 1 (використання -v, щоб побачити виклик)


У вас помилка лінкера. Це: (1) Xcode використовує ім’я вашого модуля продукту, а не ваше цільове ім’я, при іменуванні заголовка об’єднання Objective-C та згенерованого заголовка для вашого коду Swift, або (2) переконайтеся, що імпортуєте заголовки Objective-C для тих, хто типи перед імпортом заголовка Swift у файл Objective-C .m, з якого ви хочете отримати доступ до коду Swift? Чи є у вас: #import “ProductModuleName-Swift.h” у коді Objective-C?
petert

Так, я прочитав документацію, і назва "ProductModelName" правильна ... Існує помилка, що всередині Build Setting модель продукту не була встановлена ​​... я навіть встановив її ...
Eloreden

@petert, ти можеш пояснити краще другий момент? Я писав колись, що я робив ...
Елореден

Вирішена проблема, я додав новий файл .h у своєму виклику проекту <ProductModelName> -Swift.h, але це не потрібно, оскільки компілятор просто створює цей об'єкт, навіть якщо я його не бачу. Я видалив новий файл, який я створив, і тепер все працює ідеально. Tnx petert
Елореден

Ви можете відповісти на власні запитання - це може допомогти іншим.
petert

Відповіді:


50

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

Просто включіть <ProductModuleName>-Swift.hу свій клас, і він повинен спрацювати.


3
як щодо функцій з параметрами?
Arnlee Vizcayno

3
Я не можу отримати доступ до функцій Swift з параметрами та значенням, що повертається, а також не можу отримати доступ до функцій Swift без параметрів і без значення, що повертається. Не знаю чому. Мій клас Swift - це об’єкт NSO, я імпортував основу Foundation, клас і функції мають @objcпрефікс. Файл -Swift.hбуло створено автоматично. Головне болить у мене те, що я можу зателефонувати до самого класу, але не до будь-якої функції всередині нього. Хтось знає чому?
Девід öелжузер

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; @end

Ви також можете замінити ім'я Obj-C вашого класу Swift, використовуючи@objc (MyClassName)
nielsbot

12
Для тих, хто може зробити ту ж тупу помилку, що і я. На кроці 2 обов’язково використовуйте (ProjectName)-Swift.h, НЕ (ClassName)-Swift.h !
Хлунг

спасибі @Svitlana, неймовірно, це спрацювало !!! Але мені доводиться багато разів повторювати ці кроки, включаючи переміщення моїх доданих методів в інші місця класу.
Скофілд Тран

1
3) @class SwiftClassName;мене врятувало
Мазен Кассер

33

Припустимо, що у нас є ProjectName "MyFirstProjectOnSwift" та швидке ім'я класу "mySwiftClass", а classC - "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 Це не повинно бути, подумайте, чисті похідні дані та відкрийте свій проект.
Анубхав Гірі

12

Перевірте файл -Swift.h, який імпортує ваш файл .m у цілі-C:

#import <YourProjectName-Swift.h>

Клацніть на цьому рядку та клацніть лівою кнопкою миші - Перейти до визначення.

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


2

Якщо ви все ще не бачите свого класу навіть після імпорту <ProductModuleName>-Swift.h.

Переконайтеся, що ваш клас підкласує власний клас (наприклад UIViewController), або, принаймні, якщо це просто клас утиліти, зробіть його підкласом NSObject. Тепер повинен показатись ваш клас.


2

Маленька додаткова порада для тих, хто натрапляє на цю публікацію, а для кого інші відповіді не працюють: можливо, вам також доведеться оголосити свій клас Swift "загальнодоступним".

Приклад:

@objc public class MySwiftClass: NSObject {


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. У ньому також обговорюється прапорець “Назва модуля продукту”.

Хоча це теоретично може відповісти на питання, переважно було б включити сюди основні частини відповіді та надати посилання для посилання.
Арг'я Садху
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.