Swift Combine removeDuplicates () не работает должным образом - PullRequest
0 голосов
/ 06 марта 2020

Я пытаюсь отфильтровать только ориентации .portrait и .landscape, а затем применить метод DifferentUntilChanged, т.е. removeDuplicates ()

Но, похоже, removeDuplicates () никогда не вызывается, поскольку мой отладчик никогда не останавливается внутри компаратора

и вызывается обратный вызов onReceive.

 // MARK: - Publishers
    private var orientationChange = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
        .map { toOrientation($0) }
        .filter { filterOrientation($0) }
        //.removeDuplicates()
        .removeDuplicates(by: { o1, o2 in
           _ = filterOrientation(o1)
           _ = filterOrientation(o2)
            return false
        })
        .receive(on: DispatchQueue.main)

Как разрешить только последовательности .portrait, .landscape, .portrait, .landscape и не .portrait, .portrait, .landscape et c

Обновление

Мне нужно использовать это, но он добавляет ненужный шаблонный код:

.onReceive(orientationChange) { orientation in
                guard orientation != self.lastOrientation else { return }
                self.lastOrientation = orientation

}

Вот внутренние реализации вспомогательных функций

fileprivate func toOrientation(_ notification: UIKit.Notification) -> UIDeviceOrientation {
    (notification.object as? UIDevice)?.orientation ?? .unknown
}

fileprivate func filterOrientation(_ orientation: UIDeviceOrientation, orientations: [UIDeviceOrientation] = [.landscapeLeft, .landscapeRight, .portrait, .portraitUpsideDown]) -> Bool {

    return orientations.contains(orientation)
}

1 Ответ

0 голосов
/ 06 марта 2020

Одним простым решением при использовании Publishers в SwiftUI View является добавление @ State

// MARK: - Publishers
    @State private var orientationChange = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
        .map { toOrientation($0) }
        .filter { filterOrientation($0) }
        .removeDuplicates()
        .receive(on: DispatchQueue.main)

В противном случае этот издатель будет воссоздан при каждом перерисовке представления, так что теряет события изменения ориентации и не может удалить removeDuplicates, так как при вращении всегда генерируется одно событие

Другой способ, если вы используете ViewModel : ObservableObject Я думаю, что было бы хорошо переместить этого издателя туда и добавить свойство @ObservedObject в представлении SwiftUI.

...