Development record of developer who study hard everyday.

, ,

How to implement MVVM pattern using SwiftUI and Combine

How to implement MVVM pattern using SwiftUI and Combine



1. ContentView.swift

import SwiftUI


struct ContentView: View {
    //You have to declare viewModel as @ObservedObject, so you can bind viewModel's property
    //to SwiftUI's view

    @ObservedObject private var viewModel: ViewModel

    init(viewModel: ViewModel) {

        self.viewModel = viewModel

    }

    

    var body: some View {

        VStack {

            

            Text(String(viewModel.count))

            

            Spacer().frame(height: 10)


            Button(action: {

                viewModel.plus()

            }, label: {

                Text("Plus")

            })

            

            Spacer().frame(height: 10)

            

            Button(action: {

                viewModel.minus()

            }, label: {

                Text("Minus")

            })

            

            Spacer().frame(height: 20)

            

            Text(viewModel.inputText)

            

            Spacer().frame(height: 10)

            

            Text(viewModel.descriptionText)


            Spacer().frame(height: 10)

            
            //Using $, you can store user's inputText in viewModel's property

            TextField("텍스트를 입력하세요", text: $viewModel.inputText)

                .frame(alignment: .center)

                .multilineTextAlignment(.center)

                .keyboardType(.default)

        }

        .padding()

    }

}


#Preview {

 

    ContentView(viewModel : ViewModel())

}


2. ViewModel.swift

import Foundation

import Combine


//ViewModel have to inherit ObservableObject for MVVM pattern

class ViewModel: ObservableObject {

    

    init() {

        print("ViewModel init")

        
        //Subscribe descriptionPublisher and assign value to descriptionText property

        descriptionPublisher

            .receive(on: RunLoop.main)

            .assign(to: \.descriptionText, on: self)

            .store(in: &cancellableBag)

    }

    
    //You can publish data and subscribe data using @Published

    @Published var count: Int = 0

    @Published var inputText: String = ""

    @Published var descriptionText: String = ""
    //Subscribe inputText data and transform data using map method

    var descriptionPublisher : AnyPublisher<String, Never> {

        return $inputText

            .map { "현재 텍스트의 길이는 " + String($0.count) + "입니다." }

            .eraseToAnyPublisher()

    }

    

    private var cancellableBag = Set<AnyCancellable>()

    

    func plus() {

        print("viewModel plus called")

        count += 1

    }

    

    func minus() {

        print("viewModel minus called")

        count -= 1

    }

    

    deinit {

        cancellableBag.removeAll()

    }

}


The full code is in below url:

https://github.com/antwhale/SampleCombineCounter


Share:

댓글 없음:

댓글 쓰기