Как Swift взаимодействует с Objective-C?
Swift и Objective-C взаимодействуют через bridging header (ObjC → Swift) и автогенерируемый ModuleName-Swift.h (Swift → ObjC). Swift-классы должны наследоваться от NSObject и быть помечены @objc, чтобы стать видимыми из ObjC.
Swift и Objective-C: взаимодействие
Swift и Objective-C могут сосуществовать в одном проекте благодаря специальному bridging-слою, который Xcode и компилятор генерируют автоматически. Это позволяет постепенно мигрировать ObjC-кодовые базы на Swift без переписывания с нуля.
Использование Objective-C из Swift
В app target создаётся bridging header: ModuleName-Bridging-Header.h. Любой #import в нём делает соответствующие ObjC-классы и функции видимыми в Swift.
// MyApp-Bridging-Header.h
#import "LegacyParser.h"
#import <SomeObjCLibrary/SomeObjCLibrary.h>
// Swift-файл
let parser = LegacyParser()
parser.parse("input") // вызов ObjC-метода из Swift
Для фреймворков и SPM-пакетов bridging header недоступен — там используют module map: файл module.modulemap, определяющий ObjC-модуль, который Swift может импортировать напрямую через import ModuleName.
Использование Swift из Objective-C
Компилятор автоматически генерирует заголовок ModuleName-Swift.h. Чтобы класс или метод попал в этот заголовок, необходимо:
- Класс должен наследоваться от
NSObject(или быть@objcс ограничениями). - Метод/свойство должны быть помечены
@objcявно или неявно (через@objcMembers). - Должны использоваться только типы, совместимые с ObjC (нет generics, нет enums с associated values).
// Swift
@objc class UserManager: NSObject {
@objc var currentUser: String = ""
@objc func login(username: String, completion: @escaping (Bool) -> Void) {
// ...
completion(true)
}
}
// Objective-C
#import "MyApp-Swift.h"
UserManager *manager = [[UserManager alloc] init];
[manager loginWithUsername:@"alice" completion:^(BOOL success) {
NSLog(@"Login: %d", success);
}];
Маппинг типов
String↔NSString— автоматический bridge, без копирования.Array<T>↔NSArray,Dictionary↔NSDictionary,Set↔NSSet.Int,Double,Bool↔NSNumberчерезascast.- Swift
Optional→ ObjC nullable pointer;String?→NSString * _Nullable. - Swift enums без associated values и с
@objc→ ObjC enum (Int raw value).
Nullability аннотации в ObjC для Swift
Чтобы Swift не импортировал все ObjC-указатели как ImplicitlyUnwrappedOptional, добавляйте аннотации в ObjC-заголовках:
// ObjC (LegacyParser.h)
NS_ASSUME_NONNULL_BEGIN
@interface LegacyParser : NSObject
- (nullable NSString *)parse:(NSString *)input error:(NSError **)error;
@end
NS_ASSUME_NONNULL_END
@objc(name) для переименования
@objc(RWUserSession)
class UserSession: NSObject {
@objc(startWithToken:)
func start(token: String) { }
}
Подводные камни
- Generics не экспортируются в ObjC — Swift generic classes и methods невидимы в Objective-C; нужно создавать non-generic обёртки.
- Swift-only типы ломают interop — struct, enum с associated values, protocol with associated types, actor — всё это не может быть представлено в ObjC.
- Циклические импорты — ObjC-файл импортирует Swift-заголовок, а Swift-файл через bridging header импортирует тот же ObjC-файл → ошибка компиляции. Решение: forward declaration в ObjC.
- Производительность bridging коллекций — конвертация
Array<String>вNSArrayпри каждом вызове — O(n) копирование; критично в tight loops. - @objcMembers захватывает всё — аннотация делает публичным весь класс, включая методы, которые вы не планировали expose-ить в ObjC; предпочитайте явные @objc на конкретных членах.
- Исключения ObjC не ловятся в Swift — ObjC
@throwминует Swifttry/catch; нужен ObjC-враппер с NS_ERROR_ENUM или tryBlock. - Изменение сигнатуры ломает ObjC-вызывающих — переименование Swift-параметра меняет ObjC selector; используйте
@objc(newName:)для обратной совместимости.
Common mistakes
- Сводить «Swift взаимодействует с Objective-C» к синтаксису и не объяснять модель памяти.
- Игнорировать жизненный цикл, основной поток или момент освобождения ресурсов в сценарии swift-29.
- Выбирать API по привычке, не проверяя состояние, ошибки, доступность и платформенные ограничения.
What the interviewer is testing
- Формулирует точную модель для «Swift взаимодействует с Objective-C» и подтверждает ее корректным примером.
- Умеет связать ответ с система типов, тестированием и отладкой на устройстве.
- Называет ограничения подхода swift-29, включая производительность, память и сопровождение.