Bazı işlevlerin genel ve bazılarının benimkilerle iletişim kurarken ne kadar içsel olmasını istediğinizi en iyi uygulamanın ne olduğunu merak ediyorum.
Bir çerçeve olarak AVPlayer
sarmasını Swift 3 içinde bir AudioManager yazıyorum.
Bazı yöntemlerin herkese açık olmasını istiyorum, böylece örn. AudioManager'dan yararlanan bir ViewController bazı yöntemlere erişebilir, ancak bazı yöntemler
çerçevesinin dışına çıkmayacaktır -> i.e. public
yerine erişim değiştiricisi internal
.
Protokol odaklı tasarım ile çerçeve yazıyorum, neredeyse her bölüm bir protokol olmalıdır.
Bu yüzden protokoller çerçeve içindeki protokollerle konuşuyor.
E.g. Ana sınıf - AudioManager
- AudioPlayer
içeriyor ve internal
işlevlerini,
vb. pause(reason:)
ancak bu yöntem internal
olmalıdır ve çerçevenin dışında gösterilmemelidir.
İşte bir örnek.Swift Dahili işlevler ve özelliklere sahip Genel iletişim kuralları
func pauseBecauseOfRouteChange() {
guard let internalPlayer = audioPlayer as? InternalAudioPlayerProtocol else { return }
internalPlayer.pause(reason: .routeChange)
}
Ama daha zarif bir çözüm olup olmadığını merak ediyorum:
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()
}
}
ben böyle bakmak yöntemi pauseBecauseOfRouteChange
değiştirerek işe alabilirim biliyor? AudioPlayerProtocol
InternalAudioPlayerProtocol
yeniler olduğunu işaretleme gibi
şey ...
Yoksa dost programcılar bunu nasıl yapacağım?
Çerçeve, iç kullanım için tasarlanmış yöntemleri ve değişkenleri ortaya çıkarmazsa daha güzeldir!
Teşekkürler!
Birisi çerçevesini kullanarak AudioPlayerProtocol
için bir uzantı yazmak istediği bir senaryo, ne kadar sonra pause(reason:)
düşünün: