Combine 실습 1

yongbeom kwak·2022년 7월 24일
0

Combine

목록 보기
2/5

이전에 배운 내용을 토대로 간단한 Combine을 이용한 실습과제를 진행해 보았다.
해당 과제는 개발하는 정대리님의 비밀번호 매치 영상에 나온 것을 구현해 보았다.

레이아웃 구성


구독 현황

//
//  ViewController.swift
//  CombineProjcet1
//
//  Created by yongbeomkwak on 2022/07/24.
//

import UIKit
import Combine
class ViewController: UIViewController {
    @IBOutlet var passwordTextField: UITextField!
    @IBOutlet var passwordConfirmTextField: UITextField!
    @IBOutlet var myBtn: UIButton!
    
    
    var viewModel : MyViewModel!
    private var mySubscriptions = Set<AnyCancellable>()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        viewModel = MyViewModel()
        
        passwordTextField
            .myTextPublisher
            .print()
        //스레드 - 메인에서 받겠다
            .receive(on: DispatchQueue.main)
        //구독
            .assign(to: \.passwordInput, on: viewModel) //KVO
            .store(in: &mySubscriptions)
        
        
        passwordConfirmTextField
            .myTextPublisher
            .print()
        //스레드 - 메인에서 받겠다
            .receive(on: DispatchQueue.main)
        //구독
            .assign(to: \.passwordConfirmInput, on: viewModel) //KVO
            .store(in: &mySubscriptions)
        
        
        
        //버튼이 뷰모델의 isMatchPasswordInput Publisher를 구독
        
        viewModel.isMatchPasswordInput
            .receive(on: RunLoop.main)
        //구독
            .assign(to: \.isVaild, on: myBtn)
            .store(in: &mySubscriptions)
    }
    
    
}

extension ViewController{
    
    final class MyViewModel {
        
        //@published 어노테이션을 통해 구독이 가능하도록 설정
        @Published var passwordInput: String = ""
        @Published var passwordConfirmInput : String = ""
        
        
        lazy  var isMatchPasswordInput : AnyPublisher<Bool, Never> = Publishers
        //passwordInput과 Confirm 두개의 가장 마지막 변경값을 사용
            .CombineLatest($passwordInput,$passwordConfirmInput)
            .map({ (password:String, passwordConfirm:String) in
                
                if password == "" || passwordConfirm == "" {
                    return false
                }
                
                if password == passwordConfirm {
                    return true
                }
                else {
                    return false
                }
            })
            .print()
            .eraseToAnyPublisher()
    }
}

extension UITextField{
    var myTextPublisher : AnyPublisher<String, Never> {
        
        NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: self) //textDidChange알림 받기
        //UITextFiled 가져옴
            .compactMap{$0.object as? UITextField}
        
        //text가져옴 String?
            .map{$0.text ?? ""}
        
        //string을 AnyPublisher로 변환하여 최종 리턴
            .eraseToAnyPublisher()
        
        
    }
}

extension UIButton {
    var isVaild: Bool {
        
        get {
            backgroundColor == .yellow
        }
        
        set {
            //newValue가 true면 background yellow 아니면 .lightGray
            backgroundColor = newValue ? .yellow : .lightGray
            isEnabled = newValue
            setTitleColor(newValue ? .blue : .white, for: .normal)
        }
    }
}

정리

ViewModel은 각 각의 TextField의 값을 구독하고
Button은 반대로 ViewModel의 isMatchPasswordInput을 구독한다.

새로배운 함수

.CombineLatest(publish value1,publish value2)
두 값 중 하나만 변해도 호출되면 두 값의 가장 최근 값을 사용한다.

profile
IOS개발 공부생

0개의 댓글