Подтвердить что ты не робот

Использование общего класса Swift в Objective-C

Скажем, я определяю общий класс в Swift, аналогичный следующему:

class MyArray<T> {
    func addObject(object: T) {
        // do something... hopefully
    }
}

(Я знаю, что есть немного лучшая реализация массива, это просто пример.)

В Swift я могу использовать этот класс очень легко:

let a = MyArray<String>()
a.addObject("abc")

С Xcode 7 теперь у нас есть дженерики в Objective-C, поэтому я бы предположил, что могу использовать этот класс в Objective-C:

MyArray<NSString*> *a = [[MyArray<NSString*> alloc] init];
[a addObject:@"abc"];

Однако MyArray никогда не добавляется в мой файл Project-Swift.h. Даже если я изменил его наследование из NSObject, он все равно не появляется в моем файле Swift.h.

Есть ли способ создать общий класс Swift, а затем использовать его в Objective-C?


Обновление: Если я пытаюсь наследовать из NSObject и комментировать @objc:

@objc(MyArray)
class MyArray<T>: NSObject {
    func addObject(object: T) {
        // do something... hopefully
    }
}

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

Общие подклассы классов @objc не могут иметь явный атрибут @objc, потому что они не видны непосредственно из Objective-C.

Означает ли это, что нет возможности использовать общий класс Swift в Objective-C?

Как косвенно ссылается класс?

4b9b3361

Ответ 2

В некоторых ситуациях есть обходной путь, когда вам нужно импортировать универсальный класс Swift в Objective-C.

Допустим, у вас есть сервис Swift REST, который использует Generics. Я использую фреймворк Moya и вот так выглядит мой сервис:

 class AuthService: BaseService<AuthAPI> {
    func register(email: String)  {
       // ... 
    }
 }

Он унаследован от базовой службы с использованием обобщений, поэтому я не могу использовать его непосредственно в своем коде Objective-C.

Итак, вот обходной путь:

Давайте создадим AuthServiceProtocol:

@objc protocol AuthServiceProtocol {
    func register(email: String)
}

Затем давайте создадим фабрику для обслуживания (или одноэлементный метод, без разницы):

@objc class Services: NSObject {
    static let authService: AuthServiceProtocol = AuthService()
}

Затем я могу вызвать свой универсальный сервис аутентификации Swift из кода Objective-C:

- (void)someObjcMethod {
    [Services.authService registerWithEmail:self.email];
}

Ответ 3

Это утомительно и уродливо, но вы можете определить универсальный класс в Swift, а затем раскрыть его специализации в Objective-C:

public class MyArray<T> {
  public func addObject(object: T) {
    // do something... hopefully
  }
}

@objc
public class MyArrayOfAny: MyArray<Any> {
  @objc
  public override func addObject(object: Any) {
    super.addObject(object: object)
  }
}

@objc
public class MyArrayOfString: MyArray<String> {
  @objc
  public override func addObject(object: String) {
    super.addObject(object: object)
  }
}