SwiftUI onChange для классов размеров horiz / vert?

#ios #swift #swiftui

#iOS #swift #swiftui

Вопрос:

Я пытаюсь создать приложение для ios (в ios 14), которое реагирует на изменения в текущих классах размеров. В частности, у меня есть модель данных, для которой я хочу установить разные значения на основе классов размера представления. Мне труднее всего понять, как это сделать.

Чтобы было ясно — я не хочу что-то менять в представлении на основе класса размера. Я хочу что-то изменить в модели данных, которая, по моему скромному мнению, не должна «знать» о представлении.

Я пытаюсь установить onChange обработчик в своем корневом представлении в SwiftUI, но не могу придумать правильное заклинание, чтобы изменение любого из классов размера (horiz / vert) вызывало срабатывание моего onChange обработчика.

Другими словами, я пытаюсь запустить произвольный код при изменении класса размера.

Если это имеет смысл для любого из гораздо более талантливых разработчиков ios на SO, пожалуйста, дайте мне знать. Если есть какая-либо дополнительная информация, которую я могу предоставить, пожалуйста, спросите.

Большое спасибо!

Комментарии:

1. Не могли бы вы показать свой код?

Ответ №1:

Вы можете использовать GeometryReader для обновления последней ширины / высоты пользовательского интерфейса до модели представления. При размещении встроенного оператора if внутри представления метод «vm.render» будет вызываться при каждом изменении размера GeometryReader. Кроме того, в отличие от .onAppear() этот оператор if вызывается при изменении ориентации.

Казалось гораздо менее сложным использовать GeometryReader со встроенным оператором if, чем подключать события ориентации с помощью: UIDevice.current.beginGeneratingDeviceOrientationNotifications() , плюс subscribe , плюс .onReceive(NotificationCenter.default.publisher …

Я совершенно уверен, что этот метод не вызывает небезопасный рендеринг контента, поскольку он блокирует все дочернее содержимое до тех пор, пока метод не будет оценен. Если кто-нибудь знает о проблеме с настройкой переменных во внешнем классе в середине визуализации, дайте мне знать. Это кажется до жути простым, пока что без недостатков.

 import SwiftUI

fileprivate class viewModel: ObservableObject {
    private var _uiLastSize:CGSize = CGSize(width:0, height:0)
    
    public func render(_ size:CGSize) -> Bool {
        guard size != CGSize.zero else {
            return false
        }

        if size != _uiLastSize {
            print("resize")
            _uiLastSize = size
        }

        return true
    }
}

struct TesterView: View {
    
    @ObservedObject private var vm:viewModel
    init() {
        vm = viewModel()
    }
            
    var body: some View {
        GeometryReader { geo in
            if vm.render(geo.size) {
                ZStack {
                    Color.blue
                    Text("Orientation: (geo.size.width > geo.size.height ? "landscape" : "portrait")")
                }
            }
        }
    }
}