Last active
          October 1, 2024 06:13 
        
      - 
      
- 
        Save defagos/4effeed15031c1a59725e4f10b540ee9 to your computer and use it in GitHub Desktop. 
    Send a message to the UIKit responder chain from a SwiftUI view
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | @objc protocol ExampleActions: AnyObject { | |
| func pushUIKitViewController() | |
| } | |
| struct ExampleView: View { | |
| @FirstResponder private var firstResponder | |
| var body: some View { | |
| Button { | |
| firstResponder.sendAction(#selector(ExampleActions.pushUIKitViewController)) | |
| } label: { | |
| Text("Push some UIKit view controller") | |
| } | |
| .responderChain(from: firstResponder) | |
| } | |
| } | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | import SwiftUI | |
| extension View { | |
| /** | |
| * Provide access to the `UIKit` responder chain, rooted in a first responder inserted where the modifier | |
| * is applied. | |
| */ | |
| func responderChain(from firstResponder: FirstResponder) -> some View { | |
| background(ResponderChain(firstResponder: firstResponder)) | |
| } | |
| } | |
| /** | |
| * A view providing access to the `UIKit` responder chain. | |
| */ | |
| private struct ResponderChain: UIViewRepresentable { | |
| let firstResponder: FirstResponder | |
| func makeUIView(context: Context) -> UIView { | |
| .init() | |
| } | |
| func updateUIView(_ uiView: UIView, context: Context) { | |
| firstResponder.view = uiView | |
| } | |
| } | |
| /** | |
| * Provide access to a first responder. A property wrapper is used as syntactic sugar, and a class | |
| * is required for mutation of the view property during SwiftUI body updates. | |
| */ | |
| @propertyWrapper class FirstResponder { | |
| fileprivate weak var view: UIView? | |
| var wrappedValue: FirstResponder { | |
| self | |
| } | |
| @discardableResult | |
| func sendAction(_ action: Selector, for event: UIEvent? = nil) -> Bool { | |
| UIApplication.shared.sendAction(action, to: nil, from: view, for: event) | |
| } | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment