HomeiOS Developmentios - SwiftUI - Utilizing customized popover reset Picker values to inital...

ios – SwiftUI – Utilizing customized popover reset Picker values to inital earlier than dismiss


I used complete code from this web site to create customized SwiftUI popover.

I wished to check it, so I created customized mannequin:

struct Mannequin {
    var someInit = 0
}

After which created ContentView:

struct ContentView: View {
    @State non-public var mannequin: Mannequin = .init()
    @State non-public var bool: Bool = false
    
    var physique: some View {
        Button("Press me") {
            bool.toggle()
        }
        .alwaysPopover(isPresented: $bool) {
            Picker("", choice: $mannequin.someInit){
                ForEach(1...30, id: .self){
                    Textual content("($0)")
                        .tag($0)
                }
            }
            .pickerStyle(.wheel)
        }
    }
}

And code for customized popover is

non-public extension UIResponder {
    func closestVC() -> UIViewController? {
        var responder: UIResponder? = self
        whereas responder != nil {
            if let controller = responder as? UIViewController {
                return controller
            }
            responder = responder?.subsequent
        }
        return nil
    }
}

non-public struct InternalAnchorView: UIViewRepresentable {
    typealias UIViewType = UIView
    let uiView: UIView

    func makeUIView(context: Self.Context) -> Self.UIViewType {
        uiView
    }

    func updateUIView(_ uiView: Self.UIViewType, context: Self.Context) { }
}

extension View {
    public func alwaysPopover<Content material>(isPresented: Binding<Bool>, @ViewBuilder content material: @escaping () -> Content material) -> some View the place Content material : View {
        self.modifier(AlwaysPopoverModifier(isPresented: isPresented, contentBlock: content material))
    }
}

struct AlwaysPopoverModifier<PopoverContent>: ViewModifier the place PopoverContent: View {
    
    // Workaround for the lacking `@StateObject` in iOS 13.
    non-public struct Retailer {
        var anchorView = UIView()
    }
    @State non-public var retailer = Retailer()

    func physique(content material: Content material) -> some View {
        if isPresented.wrappedValue {
            presentPopover()
        }

        return content material
            .background(InternalAnchorView(uiView: retailer.anchorView))
    }

    let isPresented: Binding<Bool>
    let contentBlock: () -> PopoverContent

    non-public func presentPopover() {
        let contentController = ContentViewController(rootView: contentBlock(), isPresented: isPresented)
        contentController.modalPresentationStyle = .popover

        let view = retailer.anchorView
        guard let popover = contentController.popoverPresentationController else { return }
        popover.sourceView = view
        popover.sourceRect = view.bounds
        popover.delegate = contentController

        guard let sourceVC = view.closestViewControllerResponder() else { return }
        if let presentedVC = sourceVC.presentedViewController {
            presentedVC.dismiss(animated: true) {
                sourceVC.current(contentController, animated: true)
            }
        } else {
            sourceVC.current(contentController, animated: true)
        }
    }
}

class ContentViewController<V>: UIHostingController<V>, UIPopoverPresentationControllerDelegate the place V:View {
    var isPresented: Binding<Bool>

    init(rootView: V, isPresented: Binding<Bool>) {
        self.isPresented = isPresented
        tremendous.init(rootView: rootView)
    }
    
    @MainActor required dynamic init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been applied")
    }
    
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
        self.isPresented.wrappedValue = false
    }
    
    override func viewDidLoad() {
        tremendous.viewDidLoad()

        let measurement = sizeThatFits(in: UIView.layoutFittingExpandedSize)
        preferredContentSize = measurement
    }
    
    func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        return .none
    }
}

However I observed that, earlier than dismissing popover, values from ForEach are reseted to preliminary worth earlier than dismissing popover.

I attempted to make use of .onChange and monitor worth altering and utilizing .id, however unsuccessfully.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments