육식하는야채의 개발일지
article thumbnail

저장소를 이용해서 값을 주고받는 방식을 비동기 방식이라고 한다.

저장소의 역할을 담당할 객체는 데이터의 성격에 따라 다양하게 선택할 수 있다

 

가장 쉽게 사용할 수 있는 객체로는 AppDelegate 클래스가 있다. 

AppDelegate는 UIApplication 객체로부터 생명 주기 관리를 위임받아 커스텀 코드를 처리하는 역할을 한다.

하지만 이 객체는 앱 전체를 통틀어 하나만 존재하고 여러 뷰 컨트롤러 모두 접근할 수 있으며, 앱 프로세스의 생성/소멸과 운명을 함께 하므로 이 객체에 값을 저장하면 앱이 종료되지 않는 한 값을 계속 유지할 수 있다.

SceneDelegate 클래스는 UIWindowSceneDelegate를 상속받아 아래와 같은 역할을 한다.

 

  • UI 생명주기 관리:
    • 씬(scene)의 활성화, 비활성화, 전경/배경 전환 등을 처리합니다.
  • 윈도우 설정:
    • 앱의 메인 윈도우를 생성하고 설정합니다.
  • UI 상태 복원:
    • 앱이 종료되었다가 다시 시작될 때 이전 UI 상태를 복원합니다.
  • 씬 연결 및 해제:
    • 새로운 씬이 앱에 연결되거나 해제될 때의 동작을 정의합니다.
  • 외부 이벤트 처리:
    • URL을 통한 앱 열기 등 외부 이벤트에 대응합니다.

 

 

AppDelegate 객체는 앱이 종료되면 값이 사라지기 때문에

SceneDelegate 객체도 앱이 종료되면 값이 사라진다.

반영구적으로 값을 저장하려면 UserDefaults객체, CoreData객체를 사용해야 한다.

⭐️ 책에서는 AppDelegate 객체를 사용하지만 iOS13 버전 이후 SceneDelegate를 사용하게 변경되었다.

그래서 SceneDelegate로 변경해서 해보겠다.

 

📌 SceneDelegate 객체를 사용하여 값을 주고받기

SceneDelegate.swift파일에 전달받을 값을 저장할 프로퍼티들 정의한다.

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

	var window: UIWindow?
	
	var paramEmail: String?
	var paramisUpdate: Bool?
	var paramInterval: Double?
}

 

UI를 만들어주고 FormViewController.swift를 만들어서 두 번째 뷰 컨트롤러와 연결해 준다.

 

📌 SceneDelegate의 인스턴스를 가져오기

저장할 프로퍼티들을 SceneDelegate에 저장했으므로 SceneDelegate의 인스턴스를 가져온다.

여기서 , (쉼표)를 사용한 이유는

실제로 두 개의 옵셔널 바인딩을 하나의 if let 문에서 동시에 수행하고 있기 때문에 중첩 if문 대신, 로 간략하게 해결한 것이다.

if let sd = UIApplication.shared.connectedScenes.first as? UIWindowScene
if let sceneDelegate = sd.delegate as? SceneDelegate

 

🔻

if let sd = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let sceneDelegate = sd.delegate as? SceneDelegate

 

1. UIApplication.shared.connectedScenes.first 
현재 앱에 연결된 장면(scene) 중 첫 번째 것을 가져온다.

iOS13 이후부터 여러 Scene을 가질 수 있게 되었기 때문에 주요 화면만 가져오는 코드다.

 

2. as? UIWindowScene

UIApplication.shared.connectedScenes.first을 as? UIWindowScene로 다운캐스팅한다. 


다운캐스팅을 하는 이유❓

connectedScenes.first는 UIScene 타입을 반환한다. UIWindowScene의 기능이 필요하므로.

UIWindowScene은 UIScene의 서브클래스로, 윈도우와 관련된 추가 기능을 제공한다.

다운캐스팅을 통해 UIWindowScene의 특정 속성과 메서드에 접근할 수 있게 된다.

 

 

3. if let sd = UIApplication.shared.connectedScenes.first as? UIWindowScene

다운 캐스팅에 성공하면 상수 sd에 할당한다.

 

4. sd.delegate as? SceneDelegate

UIWindowScene의 delegate 속성은 기본적으로 UIWindowSceneDelegate 타입이다.

그러나  SceneDelegate에 접근하고자 하기 때문에 하위인 SceneDelegate로 다운캐스팅한다.

 

결과적으로 UIScene ▶️ UIWindowScene ▶️ UIWindowSceneDelegate ▶️ SceneDelegate 순으로 다운캐스팅했다.

 

5. 모든 조건이 충족되면, SceneDelegate 인스턴스에 접근할 수 있게 된다.

 

📌 값 할당

if let emailText = self.email.text {
	sceneDelegate.paramEmail = emailText
}
sceneDelegate.paramisUpdate = self.isUpdate.isOn
sceneDelegate.paramInterval = self.interval.value

 

@IBAction func onSubmit(_ sender: UIButton) {
		// ViewController의 인스턴스를 가져온다.
		let preVC = self.presentingViewController
		guard let vc = preVC as? ViewController else { return }
		
		// SecneDelegate의 인스턴스를 가져온다.
		if let sd = UIApplication.shared.connectedScenes.first as? UIWindowScene,
		let sceneDelegate = sd.delegate as? SceneDelegate {
			
			// 값 할당
			if let emailText = self.email.text {
				sceneDelegate.paramEmail = emailText
			}
			sceneDelegate.paramisUpdate = self.isUpdate.isOn
			sceneDelegate.paramInterval = self.interval.value
			
			dismiss(animated: true, completion: vc.updateUI)
		}
	}

 

📌 SceneDelegate에 저장한 값을 ViewController에서 출력하기

override func viewWillAppear(_ animated: Bool) {
		updateUI()
	}
	func updateUI() {
		if let sd = UIApplication.shared.connectedScenes.first as? UIWindowScene,
		   let sceneDelegate = sd.delegate as? SceneDelegate {
			
			if let email = sceneDelegate.paramEmail {
				emailLabel.text = email
			}
			
			if let update = sceneDelegate.paramisUpdate {
				isUpdateLabel.text = update ? "자동갱신" : "자동갱신안함"
			}
			
			if let interval = sceneDelegate.paramInterval {
				intervalLabel.text = "\(Int(interval))분마다"
			}
		}
	}

똑같이 SceneDelegate 인스턴스를 가져와서 값을 저장한 프로퍼티를 레이블에 출력해 주면 된다.

 

 

SceneDelegate를 활용한 방식은 직접 값을 주고받지 않기 때문에 VC1이 메모리에서 지워지더라도 값이 사라지는 일이 없다는 장점이 있다.

하지만 앱이 종료되면 값이 사라지기 때문에 반영구적으로 값을 사용하기에는 다소 부적합하다.

profile

육식하는야채의 개발일지

@육식하는야채

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!