종달랩 종다리 이야기

iOS 화면전환 및 데이터 전송방식(동기 방식)

Computer Science/Android&iOS
반응형

동기방식에서 데이터를 주고 받는 방식은 생각보다 직관적입니다.

 

Android나 일반적인 프로그램에서는 데이터를 함수를 통해서 전달하는 경우가 많습니다. 이동하려는 개체를 생성하고, 이곳에 전달할 데이터개체를 생성해서 초기값으로 넣어주고, 이동하려는 개체를 호출하는 그런 방식이 조금 일반적입니다.

 

하지만, iOS는 이부분에서 조금 더 직관적인 부분이 있습니다.

 

이제 아래 예를 통해서 해당 방식을 고민해봅시다.

 

왼쪽 ViewController는 오른쪽 ViewController에 값을 전달할거고, 오른쪽에 ViewController는 값을 전달받아서 표시하고, 수정할것입니다. 수정된 내용은 다시 왼쪽의 ViewController로 보내는 그런 순환방식입니다.

왼쪽에서 오른쪽으로 데이터를 보내고, 역시 오른쪽에서 왼쪽으로 보내는걸 상상합시다.

일단, 왼쪽에 VC를 보면 "입력되지 않았습니다."라고 표시된 3개의 값들이 있는데, 처음에는 아무런 값도 없다고 가정해봅시다.

 

먼저 중요하게 봐야 할 부분이 어느시점에 화면에 데이터값을 표시할것인가 입니다. 우선 코드를 먼저 봅시다.

 

class RegisterController: UIViewController {
  @IBOutlet var resultEmail: UILabel!
  @IBOutlet var resultUpdate: UILabel!
  @IBOutlet var resultInterval: UILabel!
  
  var paramEmail: String? = ""
  var paramUpdate: Bool? = true
  var paramInterval: Double? = 0
  
  override func viewWillAppear(_ animated: Bool){
    if let email = paramEmail{
      resultEmail.text = email
    }
    
    if let update = paramUpdate{
      resultUpdate.text = update == true ? "AutoUpdate":"No Auto"
    }
    
    if let interval = paramInterval{
      resultInterval.text = "\(Int(interval))"
    }
  }
  
  @IBAction func close(_ sender: Any){
    self.presentingViewController?.dismiss(animated: true)
  }
  
  @IBAction func showRegister(_ sender: Any){
    let uvc = self.storyboard!.instantiateViewController(withIdentifier: "FormVC")
    
    guard let vc = uvc as? FormController else {
      return
    }
    
    vc.paramEmail = self.paramEmail!
    vc.paramUpdate = self.paramUpdate!
    vc.paramInterval = self.paramInterval!
    
    uvc.modalTransitionStyle = UIModalTransitionStyle.coverVertical
    uvc.modalPresentationStyle = .fullScreen
    self.presnet(uvc, animated: true)
  }

코드를 보면 화면전환을 present형태로 하는 것을 확인할 수 있습니다. 만일 우리가 화면전환을 NavigationController로 한다면 마지막 코드를 다음과 같이 전환하면 됩니다.

 

 //self.present(rvc, animate: true)
 self.navigationController?.pushViewController(rvc, animated: true)

 

중요한 것은 3가지 입니다.

 

- 변수의 정의

- viewWillAppear()에서 화면갱신시 이전 ViewController로부터 전달받은 값으로 화면 갱신

- showRegister() 함수에서 이동할 개체를 확인한 후 해당 개체안에 정의된 변수에 직접 값을 입력

 

내용이 그렇게 어렵지 않으므로 설명은 생략하고, 나머지 ViewController의 코드를 살펴보겠습니다.

 

class FormController : UIViewController{
  @IBOutlet weak var email: UITextField!
  @IBOutlet weak var update: UILabel!
  @IBOutlet weak var interval: UILabel!
  
  @IBOutlet weak var isUpdate: UIswitch!
  @IBOutlet weak var ControlInterval: UIStepper!
  
  var paramEmail: String = ""
  var paramUpdate: Bool = false
  var paramInterval: Double = 0
  
  override func viewDidLoad(){
    self.email.text = paramEmail
    self.update.text = paramUpdate == true ? "Auto Update":"No Auto"
    self.isUpdate.setOn(paramUpdate, animated: true)
    self.interval.text = "\(Int(paramInterfal))"
  }
  
  @IBAction func onSwitch(_ sender: UISwitch){
    if sender.isOn == true{
      self.update.text = "Auto Update"
    } else {
      self.update.text = "No Auto"
    }
  }
  
  @IBAction func onStepper(_ sender: UIStepper){
    let value = Int(sender.value)
    self.interval.text = "\(value)"
  }
  
  @IBAction func onSubmit(_ sender: Any){
    let preVC = self.presentingViewController
    
    guard let vc = preVC as? RegisterController else {
      return
    }
    
    vc.paramEmail = self.email.text
    vc.paramUpdate = self.isUpdate.isOn
    vc.paramInterval = self.ControlInterval.value
    
    self.presentingViewController?.dismiss(animated: true)
  }
}

여기서도 주의깊게 볼 부분은 다음과 같습니다.

 

- 변수의 정의

- viewDidLoad()에서 외부로부터 전달받은 값으로 화면을 구성

- onSubmit() 함수에서 되돌아갈 ViewController를 그에 맞는 class로 형변환후 변수를 저장

 

여기서도 present에 대응하는 코드로 작성되었지만, NavigationController를 이용했다면 다음 함수만 변경해주면 됩니다.

 //self.presentingViewController?.dismiss(animated: true)
 self.navigationController?.popViewController(animated: true)

 

마지막으로 Segue를 통한 화면전환시의 데이터전달만 마지막으로 정리해봅시다.

 

모든 코드에서는 이동할 또는 돌아갈 ViewController를 미리 인지하고 그에 맞게 class를 변환해서 데이터를 넣어주었습니다. 그런데, Segue는 그런 과정이 없습니다. Segue를 통한 이동시에는 해당 Segue를 identifier를 통해서 호출하기만 했습니다. 그러면 데이터를 넣어주는 시점이 언제일까? 

 

- prepare()를 통해서 segue를 통한 이동/반환시에 해당 목적지를 구분해서 데이터를 넣어줍니다.

 

@IBAction func onPerformSegue(_ sender: Any){
  self.performSegue(withIdentifier: "ManualSubmit", sender:self)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?){
  let dest = segue.destination
  guard let vc = dest as? ResultViewController else {
    return
  }
  
  rvc.paramEmail = self.email.text!
  rvc.paramUpdate = self.isUpdate.isOn
  rvc.paramInterval = self.interval.value
}

prepare함수를 오버라이드해서 그 시점에 이동할 ViewController를 확인하고 데이터를 넣어주면 됩니다. Action Segue일때도 해당 함수를 통해서 데이터를 넣어주면 됩니다.

 

 

반응형