1. Instance를 통째로 넘겨주기
main에서 다른 곳에서 data를 넘겨받을 게 있을 때 self에 대한 pointer를 넘겨서 참조할 수 있게 함
ViewController.swift
@IBAction func moveToInstance(_ sender: Any) {
let detailVC = InstanceDetailViewController(nibName: "InstanceDetailViewController", bundle: nil)
detailVC.mainVC = self
self.present(detailVC, animated: true, completion: nil)
}
메인화면과 연결된 ViewController에서 Instance Property 방식으로 데이터를 넘겨주기 위해 instance detail view 로 넘어가는 버튼과 연결된 Action 코드
InstanceDetailViewController.swift
import UIKit
class InstanceDetailViewController: UIViewController {
var mainVC: ViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func sendData(_ sender: Any) {
mainVC?.dataLabel.text = "some data"
self.dismiss(animated: true, completion: nil)
}
}
ViewController에서 InstanceDetailViewController 클래스를 인스턴스화 시키고,
InstanceDetailViewController 클래스 프로퍼티인 mainVC에 ViewController를 넘겨줘서 프로퍼티를 사용할 수 있도록 한 후,
dataLabel 이라는 id를 가진 main 화면에 label에 직접 접근하여 문자열을 전달한다.
2. Segue
Stroyboard에서 화살표로
버튼에서 직접 view로 화살표를 연결하면 segue가 생긴다.
ViewController.swift
@IBOutlet weak var dataLabel: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueDetail" {
if let detailVC = segue.destination as? SegueDetailViewController {
detailVC.dataString = "abcdefg~~"
}
}
}
UIViewController 클래스에 있는 prepare라는 함수를 오버라이드하여 사용.
segue화살표 id를 segueDetail로 지정해놨기 때문에 id로 불러오고,
아직 SegueDetailView가 호출되기 전이라 메모리에 존재하지 않을 수 있기 때문에 optional로 lf let을 사용해서
detailVC에 컨트롤러를 인스턴스화 시킨다.
그리고 SegueDetailViewController의 프로퍼티 dataString에 직접 접근하여 값을 전달한다.
SegueDetailViewController.swift
import UIKit
class SegueDetailViewController: UIViewController {
@IBOutlet weak var dataLabel: UILabel!
var dataString = ""
override func viewDidLoad() {
super.viewDidLoad()
dataLabel.text = dataString
}
}
SegueDetailViewController에서는 값이 전달오지 않으면 아무것도 출력하지 않고, 전달 받은 값이 있으면 label에 전달하여 화면에 뿌려준다.
3. Instance Property
값을 직접 넘겨주는 방법
4. Delegate(delegation pattern)
대리, 위임, protocol을 정의해서 많이 사용
ViewController.swift
@IBAction func moveToDelegate(_ sender: Any) {
let detailVC = DelegateDetailViewController(nibName: "DelegateDetailViewController", bundle: nil)
detailVC.delegate = self
self.present(detailVC, animated: true, completion: nil)
}
이때, ViewController가 해당 delegate protocol을 구현하고 있어야 한다. (프로토콜 규약을 따르고 있어야 함)
class ViewController: UIViewController, DelegateDetailViewControllerDelegate {
func passString(string: String) {
self.dataLabel.text = string
}
그래서 클래스 시작 부분에 프로토콜을 따른다고 선언하고, 구현부를 만든다.
DelegateViewController.swift
import UIKit
protocol DelegateDetailViewControllerDelegate: AnyObject {
func passString(string: String)
}
class DelegateDetailViewController: UIViewController {
weak var delegate: DelegateDetailViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func passDataToMainVC(_ sender: Any) {
delegate?.passString(string: "delegate pass data")
self.dismiss(animated: true, completion: nil)
}
}
프로토콜을 선언하고, weak var로 프로토콜 인스턴스를 생성한다.
프로토콜에 선언한 함수를 호출하는 호출부는 버튼에 연결된 액션 함수 안에 작성해놓고
구현부는 화면에 뿌려질 label 요소를 갖고있는 ViewController에서 구현한다.
5. Closure 이용
호출부와 구현부를 분리한다.
ViewController.swift
@IBAction func moveToClosure(_ sender: Any) {
let detailVC = ClosureDetailViewController(nibName: "ClosureDetailViewController", bundle: nil)
detailVC.myClosure = { str in
self.dataLabel.text = str
}
self.present(detailVC, animated: true, completion: nil)
}
실제 화면에 뿌려주는 로직의 구현부를 detailVC.myClosure에서 구현한다.
ClosureDetailViewController.swift
import UIKit
class ClosureDetailViewController: UIViewController {
var myClosure: ((String) -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func closurePassData(_ sender: Any) {
myClosure?("closure string")
self.dismiss(animated: true, completion: nil)
}
}
myClosure라는 이름으로 클로저의 자료형만 잡아주고 버튼에 연결된 Action 함수에서 호출한다.
(Delegate 방식과 비슷)
6. Notification
전혀 상관 없는, 연결 포인트 없는 클래스에서도 사용 가능
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
let notificationName = Notification.Name("sendSomeString")
NotificationCenter.default.addObserver(self, selector: #selector(showSomeString), name: notificationName, object: nil)
}
@objc func showSomeString(notification: Notification) {
if let str = notification.userInfo?["str"] as? String {
self.dataLabel.text = str
}
}
@IBAction func moveToNoti(_ sender: Any) {
let detailVC = NotificationDetailViewController(nibName: "NotificationDetailViewController", bundle: nil)
self.present(detailVC, animated: true, completion: nil)
}
NotificationCenter에서 addObserver를 추가시키고,
해야할 일이 로직으로 따로 구현된 showSomeString 함수를 selecter로 지정하여 일을 수행하게 한다.
showSomeString 함수에서는 딕셔너리로 값을 전달 받는다.
키 str에 전달받은 값이 있으면 label에 뿌려주는 로직을 수행한다.
NotificationDetailViewController.swift
import UIKit
class NotificationDetailViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func notiAction(_ sender: Any) {
let notificationName = Notification.Name("sendSomeString")
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["str": "noti string"])
}
}
지정된 Notification Observer의 이름을 넣어서 딕셔너리 형태로 데이터를 전달하여 post 하면 ViewController에 있는 구현부에서
로직을 수행한다.
'💡 work work work > swift' 카테고리의 다른 글
swift 실습 - 3.1 : Setting App Clone (0) | 2022.02.14 |
---|---|
swift 실습 - 2 : Dispatch Queue (0) | 2022.02.14 |
swift 공부 - 7 : Extension, Protocol, Generic, 고차함수 (0) | 2022.02.08 |
swift 공부 - 6 : Property, Initializer, Deinitialization (0) | 2022.02.08 |
swift 공부 - 5 : 값타입, 참조타입, 클로저(수정) (0) | 2022.01.25 |
댓글