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
Источник: