Future не будет работать в кнопке так же, как в своей собственной функции
У меня есть кнопка, которая обновляет мои предстоящие уведомления с помощью Combine, и она работает достаточно хорошо, но по какой-то причине, когда я как можно точнее копирую блок внутри кнопки в его собственную независимую функцию и использую эту функцию в кнопке, это не работает.
Это работает
Button("updatePendingView") {
let future = futureUpcomingNotificationRequests()
future
.map() {
notificationRequestsToDates(notificationRequests: $0)
}
.sink(receiveCompletion: {
print("Completed with,", $0)
},
receiveValue: {
print("Recieved \($0) as an array of Dates")
upcomingNotificationDates = $0
})
.store(in: &subscriptions)
}
Это не работает (не используется окончательное закрытие для установки массива, который обновляет View
)
@State var upcomingNotificationDates: [Date] = []
@State var subscriptions = Set<AnyCancellable>()
...
Button("updatePending with future function") {
updateNotificationView(subscriptions: subscriptions) {
upcomingNotificationDates = $0
}
}
func updateNotificationView(subscriptions: Set<AnyCancellable>, closure: @escaping ([Date]) -> ()) {
var subscriptions = subscriptions
let future = futureUpcomingNotificationRequests()
future
.map() {
notificationRequestsToDates(notificationRequests: $0)
}
.sink(receiveCompletion: {
print("Completed with,", $0)
},
receiveValue: {
print("Recieved \($0) as an array of Dates")
closure($0)
})
.store(in: &subscriptions)
}
Вот моя будущая фабрика:
func futureUpcomingNotificationRequests(notificationCenter: UNUserNotificationCenter = UNUserNotificationCenter.current()) -> Future<[UNNotificationRequest], Never> {
Future<[UNNotificationRequest], Never> { promise in
print("Original")
notificationCenter.getPendingNotificationRequests { requests in
promise(.success(requests))
}
}
}
Вот моя функция для преобразования [UNNotificationReuqest]
в [Date]
s
func notificationRequestsToDates(notificationRequests: [UNNotificationRequest]) -> [Date] {
var arrayOfDates: [Date] = []
for request in notificationRequests {
let realTrigger = request.trigger as? UNCalendarNotificationTrigger
arrayOfDates.append((realTrigger?.nextTriggerDate())!)
}
// return notificationRequest.trigger as! UNCalendarNotificationTrigger
return arrayOfDates
}
Несмотря на то, что то, что находится в теле моей updateNotificationView
функции, почти идентично тому, что находится в исходной кнопке, она не обновляет массив View
. В будущем функция updateNotificationView
даже не инициализирует (?, запускает?), И я не уверен, почему.
Эта строка var subscriptions = subscriptions
— ваша проблема. Эта локальная переменная будет перераспределена (что приведет к освобождению цепочки подписчиков), как только функция вернется (до завершения работы). Если вы используете свойство struct subscriptions
, у вас будет утечка подписчиков. Вы должны обрабатывать все это в объекте модели, для которого может быть настроен один подписчик. Затем ваша кнопка будет запускать кнопку для запроса уведомлений и публикации их в PassthroughSubject
или подобном. — person yangnom schedule 03.02.2021
Проблема в том, что вы передаете
subscriptions
в качестве аргумента:Это две строчки:
Приведет к созданию НОВОГО набора (после
.store(in: &subscriptions)
), который будет выпущен в конце области (конецupdateNotificationView
).Чтобы решить эту проблему, у вас есть два варианта:
subscriptions
inout аргументом И удалитеvar subscriptions = subscriptions
.subscriptions
, не передавая его в качестве аргумента.