LetsSwifty/Swift_Bible

[iOS] : CHAPTER 05 - UISwitch로 presentingViewController 이용시 질문

Closed this issue · 3 comments

V1 V2 가 있는데 최초에는 V1에 라벨이 hidden 으로 나와있다가 V2에서 UISwitch를 on 해주면 V1에 라벨이 다시 보이게 했는데, 다시 V2로 이동했을 때 V1에 상태에 맞춰 UISwitch의 상태를 표시해 주려고 viewDidLoad 에 presentingViewController 속성을 ViewController로 타입캐스팅 해주는 부분에서 실패하고 else 문으로 빠지더라구요. 그래서 혹시나 하고 viewWillAppear 에서 같은 처리를 해줬더니 거기서는 잘 처리가 되었습니다.

질문1 : present 하고 dismiss 하면 메모리에서 해제되어 새롭게 만드는 것으로 아는데 그렇다면 viewDidLoad에서 스위치의 컨디션을 제어하는게 맞지 않는지

질문2: 왜 viewDidLoad 에서는
let preVC = self.presentingViewController
guard let vc = preVC as? ViewController else{
return
}
두번째 줄의 타입캐스팅을 실패하는가 입니다.

[ 1번에 대하여 ]
viewDidLoad()는 화면이 윈도우에 생성될 때 최초 1회에 한해서만 실행이 되기 때문에 화면간 전환을 한다고 해도 다시 실행하지 않고,
반면 viewWillAppear()는 매번 뷰가 다시 보여질 때마다 실행 됩니다.
그래서 viewWillAppear()에 작성하셨을 때는 잘 작동한 것으로 추측됩니다! 🤔
(viewDidLoadviewWillAppear 안에 각각 프린트문을 찍어보시면 눈으로 확인하실 수 있을 거에요!)

[ 2번에 대하여 ]

let preVC = self.presentingViewController
guard let vc = preVC as? ViewController else { return }

presentingViewController 에 대한 문서를 찾아보니
"If neither the current view controller or any of its ancestors were presented modally, the value in this property is nil."
라고 적혀있는데 이것과 관련이 있지 않을까요??
제가 시간이 없어 자세히 체크는 못했지만 😅

타입 캐스팅에 실패한 것인지, preVCnil 인 것인지 체크해보시고 알려주세요!

view가 메모리에서 해제됐다가 생겼다고 해서 DidLoad가 다시 호출되는게 아니었군요..! 2번의 구문 같은 경우에는 else가 실행되었습니다

우선 제가 이해한 내용이 맞는지 확실하지 않아서 간단하게 이해한 내용을 적어보자면
VC1에는 라벨과 화면 전환을 위한 버튼이 있다고 생각을 하고, 버튼을 클릭했을 때 present 메소드를 사용해서 VC2로 넘어간다고 생각을 했어요
그리고 VC2에는 switch만 있는 상태로 switch가 on 상태면 VC1으로 dismiss 됐을 때 VC1에 있는 라벨의 hidden 속성이 false가 되고 VC1 라벨의 hidden 속성에 따라 VC2 switch on / off 상태를 표시해준다고 생각을 하고 테스트를 해봤을 때

  1. 저도 dismiss가 되면 메모리에서 날아간다고 생각을 하고 VC2의 viewDidLoad에서 타입 캐스팅을 하고 진행했을 때 정상적으로 viewDidLoad를 실행해서 타입 캐스팅도 진행이 되었고, 스위치 상태도 라벨의 히든 속성에 따라 변하는 것을 확인했어요!!

  2. 타입 캐스팅이 실패하셨다면 presentingViewController에 이전 뷰컨트롤러에 대한 참조가 제대로 저장이 안되어 있을 수도 있을 거 같아요! 정확하지는 않아요 죄송해요ㅠ

간단하게 제가 테스트한 코드를 공유 드리면

// ViewController
@IBOutlet var state: UILabel!

// ---중략---

@IBAction func Move(_ sender: UIButton) {
    guard let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "SecondVC") else { return }

    present(nextVC, animated: true)
}
// SecondViewController
@IBOutlet var isON: UISwitch!

override func viewDidLoad() {
    super.viewDidLoad()
    
    guard let prevVC = self.presentingViewController as? ViewController else {
        NSLog("타입 캐스팅 실패!!")
        return
    }
    
    NSLog("Second ViewDidLoad")
    self.isON.isOn = prevVC.state.isHidden ? false : true
}

@IBAction func onSwitch(_ sender: UISwitch) {
    guard let prevVC = self.presentingViewController as? ViewController else {
        NSLog("타입 캐스팅 실패!!")
        return
    }
    
    switch(sender.isOn) {
    case true:
        prevVC.state.isHidden = false
        self.dismiss(animated: true)
        break
    case false:
        prevVC.state.isHidden = true
        self.dismiss(animated: true)
        break
    }
}