プロトコルで作業するときに、一部の機能を公開し、内部を一部にしたいときに、ベストプラクティスが何であるか疑問に思っています。
をSwift 3に貼り付けています。AVPlayer
をフレームワークとしています。
私はいくつかのメソッドを公開したいので、 AudioManagerを使用するViewControllerはいくつかのメソッドにアクセスできますが、フレームワーク
- つまりpublic
の代わりにアクセス修飾子internal
を持つメソッドの外に公開されないメソッドもあります。
私はプロトコル駆動型設計でフレームワークを書いていますが、ほとんどすべての部分にプロトコルが必要です。
プロトコルはフレームワーク内のプロトコルと話しています。
など。メインクラス - AudioManager
- はAudioPlayer
を持ち、internal
関数を
と呼び出すことができるはずです。 pause(reason:)
ですが、その方法はinternal
であり、フレームワーク外には公開されません。
ここに例があります。内部機能とプロパティを持つ公開プロトコル公開
func pauseBecauseOfRouteChange() {
guard let internalPlayer = audioPlayer as? InternalAudioPlayerProtocol else { return }
internalPlayer.pause(reason: .routeChange)
}
しかし、よりエレガントな解決策がある場合、私は疑問に思って:
internal enum PauseReason {
case byUser
case routeChange
}
// Compilation error: `Public protocol cannot refine an internal protocol`
public protocol AudioPlayerProtocol: InternalAudioPlayerProtocol {
func pause() // I want
}
internal protocol InternalAudioPlayerProtocol {
func pause(reason: PauseReason) // Should only be accessible within the framework
}
public class AudioPlayer: AudioPlayerProtocol {
public func pause() {
pause(reason: .byUser)
}
// This would probably not compile because it is inside a public class...
internal func pause(reason: PauseReason) { //I want this to be internal
// save reason and to stuff with it later on
}
}
public protocol AudioManagerProtocol {
var audioPlayer: AudioPlayerProtocol { get }
}
public class AudioManager: AudioManagerProtocol {
public let audioPlayer: AudioPlayerProtocol
init() {
audioPlayer = AudioPlayer()
NotificationCenter.default.addObserver(self, selector: #selector(handleRouteChange(_:)), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil)
}
func handleRouteChange(_ notification: Notification) {
guard
let userInfo = notification.userInfo,
let reasonRaw = userInfo[AVAudioSessionRouteChangeReasonKey] as? NSNumber,
let reason = AVAudioSessionRouteChangeReason(rawValue: reasonRaw.uintValue)
else { print("what could not get route change") }
switch reason {
case .oldDeviceUnavailable:
pauseBecauseOfRouteChange()
default:
break
}
}
}
private extension AudioManager {
func pauseBecauseOfRouteChange() {
audioPlayer.pause(reason: .routeChange)
}
}
// Outside of Audio framework
class PlayerViewController: UIViewController {
fileprivate let audioManager: AudioManagerProtocol
@IBAction didPressPauseButton(_ sender: UIButton) {
// I want the `user of the Audio framwwork` (in this case a ViewController)
// to only be able to `see` `pause()` and not `pause(reason:)`
audioManager.audioPlayer.pause()
}
}
は、私はそれがこのように見えるようにする方法pauseBecauseOfRouteChange
を変更することにより、仕事を得ることができます知っていますか? AudioPlayerProtocol
がInternalAudioPlayerProtocol
洗練ことマーキングなどの
何か...
それとも仲間のプログラマがそれをどのように行うのですか?
フレームワークは、内部使用を意図したメソッドや変数を公開しないと、より美しくなります。
ありがとうございます!