Чи може код-c викликати швидке розширення в класі?


94

Я шукав деякі повідомлення, я думаю, що не можу написати розширення за допомогою swift і викликати його з коду Objective-C, так?

@objc, як атрибути, підтримують лише методи, клас, протоколи?


1
Чому б вам просто не спробувати?
МАЄ

7
ide скаржився на помилку, але я хочу отримати певний відповідь.
sprhawk

Відповіді:


84

Ви можете написати розширення Swift і використовувати його в коді Objective-C. Тестується за допомогою XCode 6.1.1.

Все, що вам потрібно зробити, це:

  • створити своє розширення в Swift (без @objcанотацій)

  • #import "ProjectTarget-Swift.h" у класі Objective-C (де "ProjectTarget" представляє ціль XCode, з якою пов'язане розширення Swift)

  • викликати методи із розширення Swift

Оновлення: станом на згаданий @Rizwan Ahmed, вам потрібно додати @objcанотацію:

Станом на Swift 4.0.3, анотація @objc потрібна, якщо ви хочете використовувати розширення у файлах класу Objective C.


6
Я зробив саме це, але це все ще помилка часу компіляції. Мда. РЕДАГУВАТИ: я імпортував містковий заголовок замість "ProjectTarget-Swift.h". Der.
Джейсон Ренальдо,

Обидва мости є заголовками. Різниця полягає в тому, що один призначений для використання коду Swift в ObjC, а інший - для використання коду ObjC в Swift. Заголовок Swift невидимий. Іншим, ви повинні керувати ви.
marius bardan

Вільям Ху, див. Відповідь mclaughlinj!
appleitung

39
Станом на Swift 4.0.3, анотація @objc потрібна, якщо ви хочете використовувати розширення у файлах класу Objective C.
Різван Ахмед

68

Я дізнався, що в Swift 4.0 я повинен був додати @objcперед моїм розширенням ключового слова для того , щоб методи розширення Swift , щоб стати видимим екземпляром класу ObjC я тягнуться.

Коротко:

Налаштування конфігурації файлу:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

У CustomClassExtention:

@objc extension CustomClass
{
    func method1() 
    {
        ...
    }
}

У моєму AppDelegate.m:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];

2
Якщо метод використовує загальні засоби, він не може використовувати Objective-C, і вам потрібно буде додати @nonobjcанотацію.
ThomasW 01.03.18

В якості простої позначки @objcMembers у цьому випадку не працює. Не знаю , чому .. :-(
Raunak

46

Це рішення працює для Swift 2.2 і Swift 3 . Зверніть увагу, що з Objective-C будуть доступні лише розширення для класів (не для структур або переліків).

import UIKit

extension UIColor {

    //Custom colours
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

Потім #import "ProductModuleName-Swift.h" у вашому файлі ObjC.

Швидкий 4

extension UIColor {

    // As of Swift 4.0.3, the @objc annotation is needed if you want to use the extension in Objective-C files
    @objc
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

Це не "YourProjectsNameHere ...", а швидше "YourTargetsNameHere ...": щоб ділитися цілями, вам потрібно заблокувати його на ім'я: dr2050.postach.io/post/…
Ден

1
@DanRosenstark Ви маєте рацію. Я змінюю його на "ProductModuleName-Swift.h", як пропонує Apple: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Фоті Дім

1
Чудово працює для швидких 3.
Віктор Кучера,

Чи є причина, за якою ти кажеш public, що потрібна? publicДля мене чудово працює без модифікатора. Чи ми припускаємо, що розширення знаходиться не в тому самому проекті, а імпортується з іншого проекту?
Lee Kang

Чи потрібно використовувати мостовий заголовок?
jegadeesh

42

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

Виняток з цього становить, коли категорія визначена за мостовим типом (тобто розширення визначено на, Stringа не NSString). Ці категорії не будуть автоматично пов’язані з аналогами Objective-C. Щоб обійти це, вам потрібно буде використовувати тип Objective-C (і ввести значення повернення у коді Swift за допомогою as String), або визначити розширення як для Swift, так і для Objective-C.


2
Додаючи до відповіді вище, ви повинні зробити своє швидке розширення загальнодоступним і встановити його тип як NSString, наприклад public extension NSString. Якщо під час компіляції ви отримаєте невирішений ідентифікатор або подібну помилку, ви можете знову передати дані в String, наприклад, let sVal = self as Stringа потім викликати необхідний кодsVal
RunLoop

@RunLoop насправді вам не потрібен public, він буде працювати без специфікатора області. І це (я маю на увазі експорт до Obj-C) не працює для рядків, оскільки вони є структурами, а не класами, і доступні лише від Swift. Отже, так - ви можете написати розширення для NSString і використовувати кастинг, або написати розширення, як було mclaughlinjсказано, як для класу NSString, так і для String struct
Алекс Назарський

3

Імпортуйте заголовок "#import" ProductModuleName-Swift.h " у файл-c та додайте @objc перед вашим екстенсієм у швидкий файл. Він справно працюватиме в swift 4.2 і swift 5

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