Skip to content

Instantly share code, notes, and snippets.

@alongotv
Last active November 11, 2024 14:07
Show Gist options
  • Save alongotv/7f450e8c47ed3f057e1f6d35443af269 to your computer and use it in GitHub Desktop.
Save alongotv/7f450e8c47ed3f057e1f6d35443af269 to your computer and use it in GitHub Desktop.
Adds viewDidAppear callback to SwiftUI
struct ViewControllerLifecycleHandler: UIViewControllerRepresentable {
func makeCoordinator() -> ViewControllerLifecycleHandler.Coordinator {
Coordinator(onDidAppear: onDidAppear)
}
let onDidAppear: () -> Void
func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerLifecycleHandler>) -> UIViewController {
context.coordinator
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ViewControllerLifecycleHandler>) {
}
typealias UIViewControllerType = UIViewController
class Coordinator: UIViewController {
let onDidAppear: (() -> Void)?
init(onDidAppear: (() -> Void)?) {
self.onDidAppear = onDidAppear
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
(onDidAppear ?? {})()
}
}
}
struct DidAppearModifier: ViewModifier {
let onDidAppearCallback: (() -> Void)?
func body(content: Content) -> some View {
content
.background(ViewControllerLifecycleHandler(onDidAppear: onDidAppearCallback ?? {}))
}
}
extension View {
func onDidAppear(_ perform: @escaping () -> Void) -> some View {
self.modifier(DidAppearModifier(onDidAppearCallback: perform))
}
}
@lukaskubanek
Copy link

Just stumbled upon this discussion and I think that this might be related: feedback-assistant/reports#411

@hauntii
Copy link

hauntii commented Nov 11, 2024

Had an issue where it wasn't recognizing the ViewModifier as valid, changed some stuff around and now it works:

struct ViewControllerLifecycleHandler: UIViewControllerRepresentable {
    func makeCoordinator() -> ViewControllerLifecycleHandler.Coordinator {
        Coordinator(onDidAppear: onDidAppear)
    }

    let onDidAppear: () -> Void
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerLifecycleHandler>) -> UIViewController {
        context.coordinator
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ViewControllerLifecycleHandler>) {
    }

    typealias UIViewControllerType = UIViewController

    class Coordinator: UIViewController {
        let onDidAppear: (() -> Void)?

        init(onDidAppear: (() -> Void)?) {
            self.onDidAppear = onDidAppear

            super.init(nibName: nil, bundle: nil)
        }

        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
           (onDidAppear ?? {})()
        }
    }
}

extension View {
    func onDidAppear(_ perform: @escaping () -> Void) -> some View {
        return background(ViewControllerLifecycleHandler(onDidAppear: perform))
    }
}

Hope this helps anyone else trapped on older versions of iOS!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment