一尘不染

用Objective-C类别扩展Swift类

swift

我处于需要使用Objective-C类别扩展Swift类的情况。我做了如下的事情:

在“ SomeClass.swift”中:

class SomeClass: NSObject {
}

在“ SomeClass + Extension.h”中:

#import "Project-Swift.h"
@interface SomeClass (Extension) 
-(void)someMethod();
@end

效果很好。而且,如果我尝试在我的Objective C代码中使用SomeClass扩展,那就很好了。

问题是,如果要someMethod()在另一个Swift类中使用,则需要将SomeClass+Extension.h文件放入ObjC- BridgingHeader.h文件中。

但是这样做会导致循环依赖性,因为SomeClass+Extension.h还会导致import Project-Swift.h

有谁有解决这个问题的好方法?

请注意,仅在类别标头中向前声明该类是行不通的,因为类别本身无法使用正向声明,因此:

@class SomeClass不导入Project-Swift.h将给出编译错误。


阅读 226

收藏
2020-07-07

共1个答案

一尘不染

坏人

我也一直在与这个问题作斗争。不幸的是,文档非常明确地指出不允许这种模式:

为避免循环引用,请勿将Swift代码导入到Objective-C标头(.h)文件中。相反,您可以转发声明Swift类或协议以在Objective-
C接口中对其进行引用。

Swift类和协议的前向声明只能用作方法和属性声明的类型。

同样在整个链接页面中,您会注意到它不断提及将生成的标头专门导入.m文件:

将Swift代码从同一目标导入到Objective-C

将Swift代码从该目标导入到该目标内的任何Objective-C .m文件中

善良

一个可能适合您的解决方案是创建一个快速扩展,重新定义类别中所需的每种方法。它既脆弱又丑陋,但可以说是最干净的解决方案。

/**
 Add category methods from objc here (since circular references prohibit the ObjC extension file)
 */
extension SomeClass {
    @nonobjc func someMethod() {
        self.performSelector(Selector("someMethod"))
    }
}
  • @noobjc在前面添加允许使用相同的方法签名,而无需覆盖ObjC实现
  • 现在import "SomeClass+Extension.h"可以从桥接头中删除

如果需要支持两个以上的输入参数,或者需要更紧密的类型耦合,我建议您使用运行时来调用基础函数。这里有一个很好的描述。

2020-07-07