There's an experimental annotation you can apply to public methods, @_spi.
public struct MyStruct {
public init() {}
@_spi(Private) public func myPrivateFunc() {}
}
Clients that just import ThisFramework will have access to MyStruct and MyStruct.init, but if they want to call myPrivateFunc, they need to annotate their import with a corresponding @_spi annotation with the same Private "SPI tag"
@_spi(Private) import ThisFramework
let s = MyStruct()
s.myPrivateFunc()
You can use whatever SPI tag you'd like, and you can use as many as you'd like within the module.