部分在 Objective C 中、部分在 Swift 中实现协议

mat*_*att 5 objective-c ios swift

我可以部分用 Objective C 部分用 Swift 实现协议吗?

我有一个现有的 Objective C 类,它在 .h 文件中声明如下。

@interface SetupViewController : UIViewController <UITableViewDataSource> {
    // etc.
}
Run Code Online (Sandbox Code Playgroud)

相应的.m文件实现了UITableViewDataSource协议。现在我想在 Swift 扩展中重写其中一些方法。但我希望现在不必用 Swift 重写所有这些。(这只是一个示例片段,实际的课程要长得多。)

@implementation SetupViewController

// I want to rewrite this method in Swift
/*
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2; 
}
*/

// I don't want to rewrite this method in Swift yet
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {    
    // lots of code
}
Run Code Online (Sandbox Code Playgroud)

因此,我将其中一种方法从 Objective C 文件移至我的扩展中,如下所示:

@objc extension SetupViewController {
    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // new, more involved code
    }
}
Run Code Online (Sandbox Code Playgroud)

但这不会编译。我收到一条错误消息说Method 'tableView(_:numberOfRowsInSection:)' with Objective-C selector 'tableView:numberOfRowsInSection:' conflicts with previous declaration with the same Objective-C selector. numberOfRowsInSection但是我的Objective-C文件里已经没有这个方法了,我把它拿出来了。

似乎仅仅将 UITableViewDataSource 放在 .h 文件中就会使 Swift 扩展认为已经实现了实现协议的方法。

我还尝试将扩展声明为@objc extension SetupViewController: UITableViewDataSource并将其从 .h 文件中删除,但是失败了,因为扩展本身没有实现协议。

Cri*_*tik 2

当构建一个包含 Swift+Objective-C 混合代码的项目时,以下是所发生情况的简要总结:

  1. 桥接标头已处理
  2. Swift 文件已编译
  3. Objective-C 文件已编译

您看到的错误发生在步骤#2,此时编译器认为 Objective-C 类符合UITableViewDataSource,因此它假设 Objective-C 代码实现了该tableView(_:numberOfRowsInSection:)方法,因此它会看到冲突,因为 Swift 代码也实现了方法。

问题的根源是你试图在 Objective-C 中实现一些协议方法,在 Swift 中实现一些协议方法,这是不可能的,你需要要么实现协议的所有非可选方法在 Swift 或 Objective-C 中。

如果你真的想走这条路,一个可能的解决方案是在 Swift 端移动协议一致性,并将 Objective-C 标头中的所有其他方法声明为该类的公共方法。但这可能会导致其他问题。