The projectedValue
is the property accessed with the $
operator.
Example: This code is ask the permission for Speech Recognition and show the status on UI in real time.
For projectValue, you can access that with $, as stated in description. You don’t need to specify Binding.
import SwiftUI
import Speech
struct ContentView: View {
// @Status var status: SFSpeechRecognizerAuthorizationStatus // method 1, not working
// @ObservedObject var manager = SpeechAuthManager.shared // method 2, working and simple
@SpeechAuthStatus var status // method 3, working and fancy
var body: some View {
VStack {
Text(status.description) // wrappedValue
Text($status.description) // projectedValue
}
.background(Color.blue)
.onTapGesture {
SpeechAuthManager.shared.requestSpeechRecognitionGrant()
}
} // end body
}
extension SFSpeechRecognizerAuthorizationStatus: CustomStringConvertible {
public var description: String {
return ("\(rawValue)") // because rawValue is not String, cannot used in Text
}
}
class SpeechAuthManager: ObservableObject {
// singleton
static let shared = SpeechAuthManager()
// status
@Published var authStatus: SFSpeechRecognizerAuthorizationStatus = SFSpeechRecognizer.authorizationStatus()
// request
func requestSpeechRecognitionGrant() {
SFSpeechRecognizer.requestAuthorization { authStatus in
if self.authStatus != authStatus {
DispatchQueue.main.async {
self.authStatus = authStatus
}
}
}
}
}
// monitor status
@propertyWrapper public struct SpeechAuthStatus: DynamicProperty {
@ObservedObject var manager = SpeechAuthManager.shared
let trueValues: Set<SFSpeechRecognizerAuthorizationStatus>
public init(trueValues: Set<SFSpeechRecognizerAuthorizationStatus> = [.authorized]) {
self.trueValues = trueValues
}
public var wrappedValue: SFSpeechRecognizerAuthorizationStatus {
SpeechAuthManager.shared.authStatus
}
public var projectedValue: Bool {
self.trueValues.contains(SpeechAuthManager.shared.authStatus)
}
}