如何在同一框架内访问Objective-C中的内部Swift类?

Yar*_*sim 12 frameworks access-modifiers objective-c ios swift

致力于混合框架.在Obj-C文件中导入,但内部类不可见,只有公共类.

文档清楚地说明Swift和Obj-C之间应该有内部分支:

将Swift导入Objective-C
要在与Objective-C代码相同的框架目标中导入一组Swift文件,您不需要将任何内容导入到框架的伞形头中.相反,将您的Swift代码的Xcode生成的头文件导入到您想要使用Swift代码的任何Objective-C .m文件中.因为框架目标的生成标头是框架公共接口的一部分,所以只有标记为public修饰符的声明才会出现在框架目标的生成标头中.您仍然可以在框架的Objective-C部分中使用使用内部修饰符标记的Swift方法和属性,只要它们在从Objective-C类继承的类中声明即可.有关访问级别修饰符的更多信息,请参阅 Swift编程语言(Swift 2)访问控制.

代码示例(使用框架创建新项目)

// SwiftObject.swift

public class SwiftObject: NSObject {
    public class func doSomething() {}
}

internal class YetAnotherSwiftObject: NSObject {
    internal class func doSomething() {}
}
Run Code Online (Sandbox Code Playgroud)
// SomeObject.m file

@implementation SomeObject

- (void)someMethod {
    [SwiftObject doSomething];
}

- (void)someOtherMethod {
    [YetAnotherSwiftObject doSomething]; // Use of undeclared identifier
}

@end
Run Code Online (Sandbox Code Playgroud)

Vla*_*man 19

如文档中所示,使用internal修饰符标记的声明不会出现在生成的标题中,因此编译器不会了解它们,从而引发投诉.当然,您可以使用performSelector方法发送消息,但这不方便且容易出错.我们只需要帮助编译器知道那些声明就在那里.

首先,我们需要使用@objc属性变量,它允许您在Objective-C中指定符号的名称:

// SwiftObject.swift

@objc(SWIFTYetAnotherSwiftObject)
internal class YetAnotherSwiftObject: NSObject {
    internal class func doSomething() {}
}
Run Code Online (Sandbox Code Playgroud)

然后你只需要@interface使用你想在代码中使用的方法创建声明 - 这样编译器就会很高兴,并且还会使用SWIFT_CLASS你之前指定的符号名称来应用宏 - 所以链接器会选择实际的实现:

// SomeObject.m file

SWIFT_CLASS("SWIFTYetAnotherSwiftObject")
@interface YetAnotherSwiftObject : NSObject

+ (void)doSomething;

@end


@implementation SomeObject

- (void)someOtherMethod {
    [YetAnotherSwiftObject doSomething]; // Should work now !!!
}

@end
Run Code Online (Sandbox Code Playgroud)
  • 为了清楚起见,我在.m文件中使用了接口声明,更好的选择是在.h文件中组合这些声明,并包含它.
  • 通过在该接口中声明方法,我们对编译器做出了承诺,如果你将一个不存在的方法(或错误的签名等)放在那里它就不会抱怨.显然,你会在运行时崩溃在那种情况下 - 所以要小心.

  • 尼斯?这是非常冗长和混乱的.这真的是你需要做的吗?我遇到了同样的问题,甚至苹果应该设法做比这更好的事情.我要放弃这个并回到目标c,这是不合理的!发布实际有效的内容+1(搜索后数小时). (5认同)
  • 根据Apple文档"您仍然可以使用在框架的Objective-C部分内使用内部修饰符标记的Swift方法和属性,只要它们在从Objective-C类继承的类中声明",如果swift类派生自另一个objc类,它应该在objc代码中可用.我有类似的问题,我用@objc标记了我的swift类,它继承自NSObject,但仍然没有objc代码. (4认同)

mc_*_*rum 5

对我来说,它只是通过检查:“仅允许应用扩展 API”来工作。您可以通过转到项目设置找到它,选择您的目标,然后它位于部署信息下的常规选项卡中。

有人可以向我解释一下,为什么这确实解决了问题?