2016-04-14 3 views
4

Я пытаюсь реализовать шаблон посредника со смесью Swift и Obj-C. Проблема, с которой я столкнулся, заключается в том, как бороться с использованием классов реализации протокола Swift от Obj-C. Проверьте код, чтобы увидеть, что я имею в виду:Использование реализации Swift-протокола в Obj-C

Свифта протокол и ее осуществлении:

@objc public protocol TheProtocol { 
    func someMethod() 
} 

@objc public class SwiftClass: NSObject, TheProtocol { 
    public func someMethod() { 
     print("someMethod Swift") 
    } 
} 

В ObjC-реализацию протокола:

#import "SwiftAndObjC-Swift.h" 
@interface ObjCClass : NSObject <TheProtocol> 
- (void) someMethod; 
@end 


@implementation ObjCClass 
- (void) someMethod 
{ 
    NSLog(@"someMethod ObjC"); 
} 
@end 

Мой вопрос, как это его можно определить некоторый тип в ObjC, который способен ссылаться либо на SwiftClass, либо на ObjCClass. Например, это не компилируется:

#import "SwiftAndObjC-Swift.h" 
... 
TheProtocol *p = [[ObjCClass alloc] init]; 
// Error: "Use of undeclared identifier TheProtocol" 

будет скомпилирован:

@class TheProtocol 
TheProtocol *p = [[ObjCClass alloc] init]; 

Но не р не могут быть использованы:

@class TheProtocol 
TheProtocol *p = [[ObjCClass alloc] init]; 
[p someMethod]; 
// Error: Receiver type "The Protocol" is a forward declaration" 

(Добавление забросы к заданию и/или метод вызова не помогает)

Любые решения?

ответ

11

В Objective-C протокол не является типом. Вы должны объявить класс протокол, соответствующие следующим образом:

id<TheProtocol> p = [[ObjCClass alloc] init]; 

Причина, почему ваше опережающее объявление компилируется потому, что это то, что делает вперед заявление - они объявляют компилятор, что существует класс и что компоновщик будет заполнить его позже в процессе сборки.

(Вот почему изменения в id p =... тоже работает.)

В Swift, мы объявляем классы с чем-то вроде:

class MyClass : Superclass, Protocol, AnotherProtocol { ... } 

В Objective-C мы используем это:

@class MyClass : SuperClass <Protocol, AnotherProtocol> 
// ... 
@end 

Увидеть разницу? В Swift протоколы и суперкласс смешиваются с объявлением наследования, тогда как Objective-C обрабатывает их по-разному.

Протоколы и классы обрабатываются несколько разными на двух языках, поэтому используются по-разному.

id в ObjectiveC аналогичен AnyObject? в Swift. Объектом, который соответствует SomeProtocol, является, очевидно, AnyObject или id в Objective-C.

+0

Приветствия, принято. – Gruntcakes

-2

решаемые, я просто изменил тип с идентификатором

id p = [[ObjCClass alloc] init]; 
[p someMethod]; 
+6

'id' примерно эквивалентен' AnyObject'. вы, вероятно, хотите 'id ', что означает объект, который соответствует _TheProtocol_ – nielsbot

-1

вы не используете @class объявить протокол ... вместо этого вы должны импортировать Swift заголовок совместимости, который будет содержать определение протокола ,

Кроме того, чтобы объявить объект, который соответствует протоколу в Obj C, используйте id<TheProtocol> в качестве типа

Смежные вопросы