나타난 오류 및 막힌점

RandomStudy 프로젝트 제작 중,

할 일을 추가하는 popUpView로 present 후, 데이터 추가한 뒤 dismiss로 돌아왔을때,

데이터를 전달하는 과정에서 어떻게 구성해야 할지 막히게 되었다.

델리게이트 패턴을 사용했지만 delegate = nil로 위임자를 못찾는 오류

 

두번째 접근방법: Delegate

두번째 방법은 delegate 방법이다.

PopUpVC에서 프로토콜을 선언해 데이터를 추가한다면, 프로토콜안 메서드를 데이터 받는 VC에서 메서드를 구현해 데이터를 최신화 해보려고 한다.

 

<AddVC>

// AddPopUpViewController.swift

protocol AddPopUpViewControllerDelegate: AnyObject {
    func sendedDataFromPopUp()
}

class AddPopUpViewController: UIViewController {
    weak var delegate: AddPopUpViewControllerDelegate?
    
    
     @objc func addButtonTapped() {
        guard let text = self.textField.text else { return }
        if text == "" {
            errorLabel.text = "공백은 추가할 수 없습니다."
            errorLabel.isHidden = false
        } else {
            if viewModel.isContainsElement(str: text) {
                errorLabel.text = "같은 목록이 존재합니다."
                errorLabel.isHidden = false
            } else {
                errorLabel.isHidden = true
                viewModel.addData(str: text)
                delegate?.sendedDataFromPopUp() // <--- 델리게이트 메서드
                self.dismiss(animated: true)
            }
        }
    }
   
}

-> 데이터를 보낼 곳에서 delegate을 선언해두고, 프로토콜을 만들고, 버튼을 누르면 위임자가 프로토콜의 메서드를 작동하도록 하였다.

 

<PopUpVC>

// AddViewController.swift
class AddViewController: UIViewController {
    
    private var popupVC = AddPopUpViewController()
    // 데이터 바인딩
    private func bindings() {
        popupVC.delegate = self
    }
    // PopUpVC로 가는 이벤트 메서드
     @objc func addCategory() {
        let addPopUpView = AddPopUpViewController()
        addPopUpView.modalPresentationStyle = .overFullScreen
        addPopUpView.modalTransitionStyle = .crossDissolve
        self.present(addPopUpView, animated: true, completion: nil)
    }
}
// 위임자를 본인(AddVC)로 설정하고 프로토콜의 메서드를 여기서 구현
extension AddViewController: AddPopUpViewControllerDelegate {
    func sendedDataFromPopUp() {
        viewModel.fetchData()
        DispatchQueue.main.async { [weak self] in
            self?.tableView.reloadData()
        }
    }
}

-> delegate를 addVC로 설정하고, popupVC에서 버튼을 누르면 addVC에서 구현한 프로토콜의 메서드를 작동하도록 하였다.

 

<< 실행 결과 >>

 

delegate를 설정함에도 불구하고, 위임자가 누구인지 인식을 못하는듯 하다..

 

빼먹은게 있는가 코드를 확인해보고, 델리게이트 패턴의 과정을 되짚어보았다..

1. 프로토콜 구성 

2. 데이터 보내는곳에서 delegate 선언 형식은 프로토콜

3. 데이터 보내는 버튼에서 프로토콜의 메서드 동작

4. 데이터 받는곳에서 delegate 위임자 지정

5. 프로토콜을 상속받아 메서드의 세부동작 구현

 

분명히 이대로 했는데 왜 위임자를 인식하지 못할까?

 

생각해낸 것들

1. 메모리 주소가 다르다(아마 유력)

클래스는 참조형식이다.

delegate 위임자를 선언하기위해(self) delegate가 선언된 뷰컨을 객체로 생성할 것이다.

또한 popupVC로 가기위해 popupvc객체를 생성했다.

결론적으로 popupVC객체를 두개를 만들었지만, 두개의 메모리 주소는 다르다.

// AddViewController.swift
class AddViewController: UIViewController {
	private var popupvc = AddPopUpViewController() // popupVC 객체 생성 1
	private func bindings() {
       popupvc.delegate = self
    }
    
    @objc func addCategory() {
        let addPopUpView = AddPopUpViewController()	// popupVC 객체 생성 2
        addPopUpView.delegate = self
        addPopUpView.modalPresentationStyle = .overFullScreen
        addPopUpView.modalTransitionStyle = .crossDissolve
        self.present(addPopUpView, animated: true, completion: nil)
    }
}

 

첫번째 객체 생성했을때, 메모리 현황

 

두번째 객체 생성했을때, 메모리 현황

 

아마 첫번째 객체생성의 메모리주소는 0x1088ad400, 두번째 객체생성 메모리주소는 0x10881bc00 인것 같다.

첫번째 객체에서 delegate를 위임해줬지만

실제로 popupVC로 가는 객체의 메모리주소는 두번째이므로 delegate 위임을 인식하지 못한것같다.

 

present를 통해 vc를 이동했을때, 이동하기위해 생성한 객체로 delegate 선언을 해보니 프로토콜에 정의된 메서드가 실행이 되었다!

 

+ Recent posts