swift - 为了简化面向公众的 API,如果特定于平台的类型别名为已经公开的类型别名,你能否将它们设为私有?
问题描述
标题可能看起来有点混乱,但考虑一下这种情况。我们UIView
为 iOS/iPadOS 应用程序提供了以下扩展。
import UIKit
extension UIView {
var isVisible:Bool{
get{ return !isHidden }
set{ isHidden = !newValue }
}
func addSubviews(_ subviews:UIView...) {
addSubviews(subviews)
}
func addSubviews(_ subviews:[UIView]) {
subviews.forEach{ addSubview($0) }
}
}
NSView
我们为 macOS 应用程序提供了完全相同的扩展。
import AppKit
extension NSView {
var isVisible:Bool{
get{ return !isHidden }
set{ isHidden = !newValue }
}
func addSubviews(_ subviews: NSView...) {
addSubviews(subviews)
}
func addSubviews(_ subviews: [NSView]) {
subviews.forEach{ addSubview($0) }
}
}
两者的唯一区别是一种用途UIView
,另一种用途NSView
。
为了摆脱这种冗余,并避免在任何地方添加平台检查,我们简单地给类名本身加上别名,然后围绕这些别名构建 API,就像这样......
#if os(iOS) || os(tvOS)
import UIKit
typealias PlatformView = UIView
#elseif os(OSX)
import AppKit
typealias PlatformView = NSView
#endif
extension PlatformView {
var isVisible:Bool{
get{ return !isHidden }
set{ isHidden = !newValue }
}
func addSubviews(_ subviews: PlatformView...) {
addSubviews(subviews)
}
func addSubviews(_ subviews:[PlatformView]) {
subviews.forEach{ addSubview($0) }
}
问题是我们现在必须公开PlatformView
公开,这可能会使那些导入我们的 Swift 包的人感到困惑。我们希望他们只会看到UIView
或者NSView
取决于他们的平台。
那么......是否可以隐藏您的类型别名并公开它们别名的公共类型?
解决方案
您期望的是预处理宏的行为。类型别名在编译时被替换为它们的底层类型,这使得它们与它们别名的类型相同。
但是,使用类型别名的接口仍将公开类型别名而不是底层类型,因为类型别名的主要用例之一是为其他类型提供更有意义的(至少在某些上下文中)名称或组合将几种类型(如typealias ABProtocol = AProtocol & BProtocol
)合并到一个名称中,因此不公开所述类型别名的接口将带走typealias
es 的主要用例之一。
正如我在回答开头所说的那样,您将在编译时使用预处理器宏将您的类型别名替换为表示的类型,从而在您的公共接口中公开别名类型。
然而,遗憾的是,Swift 预处理器宏没有 Obj-C 强大。您不能替换预处理器宏中的类型名称,也不能在预处理器宏中放置类型声明/扩展的开头。
因此,没有办法实现避免代码重复和必须在公共接口中公开类型别名的目标。
推荐阅读
- c# - 访问服务器上的 .Net 应用程序时出现 Json 读取错误
- docusignapi - Docusign REST API 将文档添加到现有信封
- vim - 在vim中使用:term执行命令时如何滚动结果
- unity3d - 如何在 Unity VR 中启用触摸键盘?
- function - 从函数返回的数据作为 null 进入快照
- excel - VBA Shape.Placement 属性仍然允许调整大小
- spring-boot - 使用 HttpClient 和 HttpComponentsMessageSender 设置超时有什么区别?
- python - 如何在python环境中更改时间
- r - 如何相交两个 sf 对象?
- sql - 微软访问。记录一堆列中最高数字的位置