问题描述
我已经进行了大量搜索并阅读了大量文章,但我无法让 SwiftUI 根据模型中的变量变化动态更新视图,至少是我正在做的那种事情。基本上我想根据应用程序的 UNNotificationSettings.UNAuthorizationStatus
更新视图。我让应用程序在启动时检查状态并显示状态。如果状态未确定,则点击文本将触发请求通知对话框。但是,在用户允许或拒绝通知后,视图不会更新。我确定我遗漏了一些基本的东西,因为我已经尝试了十几种方法,包括 @Published ObservableObject
、@Observedobject
、@EnvironmentObject
等。
struct ContentView: View {
@EnvironmentObject var theviewmodel : Testviewmodel
var body: some View {
vstack {
Text(verbatim: "Notifications are: \(theviewmodel.notificationSettings.authorizationStatus)")
.padding()
}
.onTapGesture {
if theviewmodel.notificationSettings.authorizationStatus == .notDetermined {
theviewmodel.requestNotificationPermissions()
}
}
}
}
class Testviewmodel : ObservableObject {
@Published var notificationSettings : UNNotificationSettings
init() {
notificationSettings = type(of:self).getNotificationSettings()!
}
func requestNotificationPermissions() {
let permissionsToRequest : UNAuthorizationoptions = [.alert,.sound,.carPlay,.announcement,.badge]
UNUserNotificationCenter.current().requestAuthorization(options: permissionsToRequest) { granted,error in
if granted {
print("notification request GRANTED")
}
else {
print("notification request DENIED")
}
if let error = error {
print("Error requesting notifications:\n\(error)")
}
else {
dispatchQueue.main.sync {
self.notificationSettings = type(of:self).getNotificationSettings()!
}
}
}
}
static func getNotificationSettings() -> UNNotificationSettings? {
var settings : UNNotificationSettings?
let start = Date()
let semaphore = dispatchSemaphore(value: 0)
UNUserNotificationCenter.current().getNotificationSettings { notificationSettings in
settings = notificationSettings
semaphore.signal()
}
semaphore.wait()
while settings == nil {
let elapsed = start.distance(to: Date())
Thread.sleep(forTimeInterval: TimeInterval(0.001))
if elapsed > TimeInterval(1) {
print("ERROR: did not get notification settings in less than a second,giving up!")
break
}
}
if settings != nil {
print("\(Date()) Notifications are: \(settings!.authorizationStatus)")
}
return settings
}
}
func getUNAuthorizationStatusstring(_ authStatus : UNAuthorizationStatus) -> String {
switch authStatus {
case .notDetermined: return "not determined"
case .denied: return "denied"
case .authorized: return "authorized"
case .provisional: return "provisional"
case .ephemeral: return "ephemeral"
@unkNown default: return "unkNown case with rawValue \(authStatus.rawValue)"
}
}
extension UNAuthorizationStatus : customstringconvertible {
public var description: String {
return getUNAuthorizationStatusstring(self)
}
}
extension String.StringInterpolation {
mutating func appendInterpolation(_ authStatus: UNAuthorizationStatus) {
appendLiteral(getUNAuthorizationStatusstring(authStatus))
}
}
编辑:我尝试添加 objectwillChange 但视图仍未更新。
class Testviewmodel : ObservableObject {
let objectwillChange = ObservableObjectPublisher()
@Published var notificationSettings : UNNotificationSettings {
willSet {
objectwillChange.send()
}
}
init() {
notificationSettings = type(of:self).getNotificationSettings()!
}
解决方法
根据苹果文档,像@Published 这样的属性包装器应该保存值。 UNNotificationSettings 是引用类型。由于类发生了变异并且指针永远不会改变,@Publushed 不知道您更改了任何内容。发布一个值(它创建一个结构并从他的类中初始化它)或手动手动发送 objectwillChange 消息。
,虽然我无法使用 public class Customer {
private String firstName,lastName;
private Date birthday;
private String address;
public Customer() {
firstName="Hans";
lastName = "Meier";
birthday = new Date(915195600000l);
address = "-";
}
public Customer(String firstName,String lastName,String address) {
this.firstName = firstName;
this.lastName = lastName;
this.birthday = new Date(915195600000l);
this.address = address;
}
public Customer (String firstName,Date birthday,String address) {
this.firstName = firstName;
this.lastName = lastName;
this.birthday = birthday;
this.address = address;
}
public Customer (Customer customer) {
firstName = customer.firstName;
lastName = customer.lastName;
birthday = customer.birthday;
address = customer.address;
}
}
手动使用它,但我确实创建了一个基本的工作系统,如下所示。上题部分功能不再赘述。
objectWillChange