Home > Software engineering >  Is delegate pattern a good approach in SwiftUI?
Is delegate pattern a good approach in SwiftUI?

Time:12-04

I am converting an iOS app from UIKit to SwiftUI. I have a UIViewController that displays a view with different buttons. This UIViewController has a delegate that conforms to a specific protocol. On each button's action, I call a method of its delegate. Nothing special here, it is a typical Delegate pattern as we all know for iOS development with UIKit.

My question is: Is it still a good approach with SwiftUI? I can totally convert this pattern in my SwiftUI app (I did already. EDIT: and as mentioned in comments, it is NOT a good idea!). But I'm wondering if this Delegate pattern is still a good way or if there is a different way to do that (with Binding maybe?). Is it recommended to use this pattern in a SwiftUI app?

Here is a simplified code example:

protocol MyCustomViewDelegate {
    func buttonATapped()
}

struct MyCustomView: View {
    public var delegate: MyCustomViewDelegate?
    var body: some View {
        Button("Button A") {
            if let delegate = delegate {
                delegate.buttonATapped()
            }
        }
    }
}

struct ContentView: View, MyCustomViewDelegate {

    var body: some View {
        MyCustomView(delegate: self)
    }

    func buttonATapped() {
        // Do something
    }
}

EDIT: Please do not use this previous implementation!

CodePudding user response:

I think that if you use closures it is better, an example to pass the function:

 struct MyCustomView: View {
        var function: () -> Void
        var body: some View {
            Button(action: {
                self.function()
            }, label: {
                Text("Button")
            })
        }
    }
    
    struct ContentView: View {
        var body: some View {
            ChildView(function: self.buttonATapped)
        }
        
        func buttonATapped() {
            print("I am the parent")
        }
    }

CodePudding user response:

import SwiftUI
protocol MyCustomViewDelegate: ObservableObject {
    func buttonATapped()
}
//I think of this as a vague UIViewController
class DelegateParentViewModel: ObservableObject{
    @Published var tappedCount = 0
}
extension DelegateParentViewModel:MyCustomViewDelegate{
    //@IBAction (ish)
    func buttonATapped(){
        tappedCount  = 1
    }
}
//I think of the View as a vague storyboard
struct DelegateParentView: View {
    @StateObject var vm: DelegateParentViewModel = .init()
    
    var body: some View {
        VStack{
            Text(vm.tappedCount.description)
            DelegateChildView(vm: vm)
            
        }
    }
}
//I think of the View as a vague storyboard
struct DelegateChildView<T:MyCustomViewDelegate>: View {
    @ObservedObject var vm: T
    var body: some View {
        Button("tap Button", action: {
            //Call IBAction (ish)
            vm.buttonATapped()
        })
    }
}
struct DelegateParentView_Previews: PreviewProvider {
    static var previews: some View {
        DelegateParentView()
    }
}
  • Related