🧑

iOS

iOS

UIKit

β€’
iOS μ•±μ—μ„œ ν•„μš”ν•œ UI μš”μ†Œλ“€μ„ μ œκ³΅ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬
β€’
μžμ£Όμ‚¬μš©ν•˜λŠ” View: UILabel, UIButton, UIImageView, UIView, UIStackView, UIScrollView, UITableView, UICollectionView, UIViewController, UINavigationViewController
// 자주 μ‚¬μš©ν•˜λŠ” View ν™œμš© μ˜ˆμ‹œ import UIKit // UIView let view = UIView() view.layer.cornerRadius = 70 view.layer.shadowOffset = CGSize(width: 5, height: 5) view.layer.shadowOpacity = 0.7 view.layer.shadowRadius = 5 view.layer.shadowColor = UIColor.gray.cgColor view.translatesAutoresizingMaskIntoConstraints = false // UILabel let label = UILabel() label.text = "ν…μŠ€νŠΈ" label.font = .systemFont(ofSize: 14) label.textColor = .black // UIButton let button = UIButton() button.setTitle("λ²„νŠΌ", for: .normal) button.setTitleColor(.systemBlue, for: .normal) button.setImage(UIImage(systemName: "heart"), for: .normal) button.addTarget(self, action: #selector(onClickButton), for: .touchUpInside) button.titlePadding = 10 // iOS 15 이상 @objc func onClickButton() { print("λ²„νŠΌμ΄ ν΄λ¦­λμŠ΅λ‹ˆλ‹€.") } // UIImageView let imageView = UIImageView() imageView.image = UIImage(systemName: "heart") imageView.contentMode = .scaleAspectFit imageView.layer.cornerRadius = 50 imageView.clipsToBounds = true //λ„˜μΉ˜λŠ” μ˜μ—­ μž˜λΌλ‚΄κΈ° // UIStackView let stackView = UIStackView() stackView.axis = .vertical stackView.alignment = .fill stackView.distribution = .equalSpacing stackView.spacing = 8 stackView.addArrangedSubview(label, button, imageView) // UITableView import UIKit class MyTableViewController: UIViewController { @IBOutlet weak var myTableView: UITableView! let friendNames: [String] = ["Henry", "Leeo", "Jay", "Key"] override func viewDidLoad() { super.viewDidLoad() myTableView.delegate = self myTableView.dataSource = self } } extension MyTableViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return friendNames.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = myTableView.dequeueReusableCell(withIdentifier: "MyFirstCell", for: indexPath) cell.textLabel?.text = friendNames[indexPath.row] return cell } }
Swift
볡사

SwiftUI

β€’
UIKit κ³Ό 같은 UI 개발 ν”„λ ˆμž„μ›Œν¬λ‘œ iOS 13 이상 버전뢀터 μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€.
β€’
SwiftUIλŠ” UI의 μƒνƒœμ— λŒ€ν•΄ μ„ μ–Έν•˜κ³  μƒνƒœκ°€ λ³€κ²½λ˜λ©΄ μžλ™μœΌλ‘œ UIλ₯Ό μ—…λ°μ΄νŠΈν•˜λŠ” 선언적 ν”„λ‘œκ·Έλž˜λ°μ„ ν•˜κ²Œ λ©λ‹ˆλ‹€.

ViewController Lifecycle

β€’
ViewController의 라이프사이클 λ©”μ„œλ“œλ₯Ό 톡해 화면이 열리고 λ‹«νžˆλŠ” μ‹œμ μ— 맞게 μ• λ‹ˆλ©”μ΄μ…˜, API μš”μ²­ λ“±μ˜ 처리λ₯Ό ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
β€’
init β†’ loadView β†’ viewDidLoad β†’ viewWillAppear β†’ viewIsAppear β†’ viewIsAppearing β†’ viewWillDisappear β†’ viewDidDisappear β†’ deinit
import UIKit class ViewController: UIViewController { let button = UIButton() override func viewDidLoad() { super.viewDidLoad() configureUI() print("viewDidLoad") } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) print("viewWillAppear") } override func viewIsAppearing(_ animated: Bool) { super.viewIsAppearing(animated) print("viewIsAppearing") } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) print("viewDidAppear") } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) print("viewWillDisappear") } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) print("viewDidDisappear") } private func configureUI() { view.addSubview(button) view.backgroundColor = .white button.setTitle("νŽ˜μ΄μ§€ 이동", for: .normal) button.addTarget(self, action: #selector(buttonTapped), for: .touchDown) button.backgroundColor = .red button.setTitleColor(.white, for: .normal) button.titleLabel?.font = .boldSystemFont(ofSize: 30) button.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ button.widthAnchor.constraint(equalToConstant: 200), button.heightAnchor.constraint(equalToConstant: 120), button.centerXAnchor.constraint(equalTo: view.centerXAnchor), button.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) } @objc private func buttonTapped() { self.navigationController?.pushViewController(AdamViewController(), animated: true) } }
Swift
볡사

λ ˆμ΄μ•„μ›ƒ

β€’
AutoLayout: iPhone κΈ°κΈ° μ‚¬μ΄μ¦ˆμ— 맞좰 μžλ™μœΌλ‘œ μ‚¬μ΄μ¦ˆλ₯Ό λ§žμΆ°μ£ΌλŠ” 것. μ œμ•½ 쑰건(Constraints)에 따라 λ·° 계측(View Hierachie) ꡬ쑰에 μžˆλŠ” λͺ¨λ“  뷰의 크기와 μœ„μΉ˜λ₯Ό λ™μ μœΌλ‘œ κ³„μ‚°ν•˜λŠ” 것
β€’
Safe area: iPhoneμ—μ„œ μ•±μ˜ 컨텐츠가 μ•ˆμ •μ μœΌλ‘œ 보이기 μœ„ν•œ μ˜μ—­μœΌλ‘œ 아이폰 κΈ°κΈ°λ§ˆλ‹€ λͺ¨μŠ΅μ΄ μ‘°κΈˆμ”© λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— Safe Area λ₯Ό κ³ λ €ν•˜μ—¬ λ·°λ₯Ό λ°°μΉ˜ν•΄μ•Όν•©λ‹ˆλ‹€.
β€’
Constraint: ConstraintλŠ” 뷰와 λ·° μ‚¬μ΄μ˜ μ œμ•½μ‘°κ±΄μ„ μ˜λ―Έν•©λ‹ˆλ‹€.
β—¦
left / right / top / bottom: 각각 쒌 / 우 / μœ„ / μ•„λž˜ μ œμ•½ 쑰건을 μ˜λ―Έν•©λ‹ˆλ‹€.
β—¦
leading / trailing: μ§€μ—­ν™”λœ 쑰건으둜 μ™Όμͺ½μ—μ„œ 였λ₯Έμͺ½μœΌλ‘œ μ½λŠ” 게 μžμ—°μŠ€λŸ¬μš΄ μ§€μ—­ 쑰건의 κΈ°κΈ°μ—μ„œλŠ” leading은 μ™Όμͺ½, trailing은 였λ₯Έμͺ½μœΌλ‘œ λŒ€μ‘λ˜κ³  λ°˜λŒ€μ˜ κ²½μš°μ—” leading은 였λ₯Έμͺ½, trailing은 μ™Όμͺ½μœΌλ‘œ λŒ€μ‘λ©λ‹ˆλ‹€.

GCD(Grand Central Dispatch)

β€’
iOS, macOS λ“±μ˜ Apple ν”Œλž«νΌμ—μ„œ λ©€ν‹°μŠ€λ ˆλ“œ ν”„λ‘œκ·Έλž˜λ°μ„ κ°„λ‹¨ν•˜κ³  효율적으둜 κ΅¬ν˜„ν•˜κΈ° μœ„ν•œ 기술. GCDλŠ” λ‹€μ–‘ν•œ μž‘μ—…μ„ κ΄€λ¦¬ν•˜κ³  μ‹€ν–‰ν•˜κΈ° μœ„ν•œ κ°•λ ₯ν•œ APIλ₯Ό μ œκ³΅ν•˜μ—¬ 병렬성을 ν™œμš©ν•  수 있게 ν•΄μ€λ‹ˆλ‹€.
β€’
νŠΉμ§•
1.
큐(Queue) 기반의 μž‘μ—… 관리: GCDλŠ” 큐λ₯Ό μ‚¬μš©ν•˜μ—¬ μž‘μ—…μ„ κ΄€λ¦¬ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μž‘μ—…μ„ μ„ΈλΆ„ν™”ν•˜κ³ , μ‹€ν–‰ν•  큐에 따라 μž‘μ—…μ˜ 속성을 κ²°μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
2.
κ°„νŽΈν•œ 비동기 μž‘μ—… 처리: GCDλ₯Ό μ‚¬μš©ν•˜λ©΄ λΉ„λ™κΈ°μ μœΌλ‘œ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” ν”„λ‘œκ·Έλž˜λ¨Έκ°€ λ³„λ„μ˜ μŠ€λ ˆλ“œλ₯Ό κ΄€λ¦¬ν•˜μ§€ μ•Šμ•„λ„ λ˜λ―€λ‘œ κ°œλ°œμ„ κ°„νŽΈν•˜κ²Œ λ§Œλ“€μ–΄μ€λ‹ˆλ‹€.
3.
큐의 μ’…λ₯˜μ— λ”°λ₯Έ λ‹€μ–‘ν•œ λ™μž‘ 방식: GCDμ—λŠ” Serial Queue와 Concurrent Queueκ°€ μžˆμŠ΅λ‹ˆλ‹€. Serial QueueλŠ” μž‘μ—…μ΄ 순차적으둜 μ‹€ν–‰λ˜λ©°, Concurrent QueueλŠ” μ—¬λŸ¬ μž‘μ—…μ΄ λ™μ‹œμ— 싀행될 수 μžˆμŠ΅λ‹ˆλ‹€.
4.
μ½œλ°±μ„ ν†΅ν•œ μž‘μ—… μ™„λ£Œ 처리: μž‘μ—…μ΄ μ™„λ£Œλ˜λ©΄ 콜백(closure)을 μ‚¬μš©ν•˜μ—¬ κ²°κ³Όλ₯Ό μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
5.
QoS(Quality of Service) 지원: GCDλŠ” 각 큐에 λŒ€ν•œ μš°μ„ μˆœμœ„ 섀정을 μ§€μ›ν•˜μ—¬ μ‹œμŠ€ν…œμ΄ μž‘μ—…μ„ 적절히 κ΄€λ¦¬ν•˜κ³  졜적의 μ„±λŠ₯을 μœ μ§€ν•  수 μžˆλ„λ‘ ν•©λ‹ˆλ‹€.
β€’
DispatchQueue.main: 메인 μŠ€λ ˆλ“œμ—μ„œ λ™μž‘ν•˜λ©°, 주둜 μ‚¬μš©μž μΈν„°νŽ˜μ΄μŠ€(UI)λ₯Ό μ—…λ°μ΄νŠΈν•˜κ±°λ‚˜ μ‚¬μš©μžμ™€μ˜ μƒν˜Έμž‘μš©μ„ μ²˜λ¦¬ν•  λ•Œ μ‚¬μš©λ©λ‹ˆλ‹€.
β€’
DispatchQueue.global(): μ „μ—­(λ°±κ·ΈλΌμš΄λ“œ) μŠ€λ ˆλ“œμ—μ„œ μž‘μ—…μ„ μ²˜λ¦¬ν•˜λŠ”λ° μ‚¬μš©λ˜λ©°, μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ λ™μ‹œμ— μ‹€ν–‰λ˜λŠ” 비동기 μž‘μ—…μ„ μ²˜λ¦¬ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€.
// λ™κΈ°μ μœΌλ‘œ μ‹€ν–‰λ˜λŠ” μž‘μ—… DispatchQueue.global().sync { print("Synchronous Task") } // λΉ„λ™κΈ°μ μœΌλ‘œ μ‹€ν–‰λ˜λŠ” μž‘μ—… DispatchQueue.global().async { print("Asynchronous Task") } // λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 비동기 μž‘μ—… μ‹€ν–‰ DispatchQueue.global().async { // μ—¬κΈ°μ„œ λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 싀행될 μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€. for i in 1...5 { print("Background Task \(i)") } // μž‘μ—…μ΄ μ™„λ£Œλ˜μ—ˆμŒμ„ 메인 μŠ€λ ˆλ“œλ‘œ μ•Œλ¦½λ‹ˆλ‹€. DispatchQueue.main.async { print("Background Task Completed, Updating UI") // UI μ—…λ°μ΄νŠΈ 등을 μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. } }
Swift
볡사

λ„€νŠΈμ›Œν‚Ή

β€’
iOSμ—μ„œ λ„€νŠΈμ›Œν¬ 톡신은 주둜 URLSession을 μ‚¬μš©ν•˜μ—¬ μˆ˜ν–‰λ©λ‹ˆλ‹€. λ„€νŠΈμ›Œν‚Ήμ€ μ™ΈλΆ€ μ„œλ²„ λ˜λŠ” 인터넷 λ¦¬μ†ŒμŠ€μ™€ 데이터λ₯Ό μ£Όκ³ λ°›λŠ” μž‘μ—…μ„ μ˜λ―Έν•˜λ©°, 비동기적인 λ°©μ‹μœΌλ‘œ μ²˜λ¦¬ν•˜λŠ” 것이 μΌλ°˜μ μž…λ‹ˆλ‹€.
//μ˜ˆμ‹œ func fetchData<T: Decodable>(for url: URL, completion: @escaping (Result<T, Error>) -> Void) { URLSession.shared.dataTask(with: url) { (data, response, error) in if let error = error { completion(.failure(error)) } if let data = data { do { let object = try JSONDecoder().decode(T.self, from: data) completion(.success(object)) } catch let decoderError { completion(.failure(decoderError)) } } }.resume() } // fetchData ν•¨μˆ˜ 호좜 let url = URL(string: "URL μ£Όμ†Œ") fetchData(for: url) { (result: Result<[WeatherMain], Error>) in switch result { case .success(let weather): print(weather) case .failure(let error): print(error) } // λͺ¨λΈ struct WeatherMain: Codable { let temp: Double let temp_min: Double let temp_max: Double let humidity: Int }
Swift
볡사

UserDefaults

β€’
κ°„λ‹¨ν•œ 데이터λ₯Ό μ‹±κΈ€ν„΄(Singleton) 객체에 Key-Value 쌍으둜 μ €μž₯ν•˜λŠ” λ°©μ‹μœΌλ‘œ 주둜 μ‚¬μš©μž μ„ΈνŒ… κ°’ 같은 μž‘μ€ 데이터λ₯Ό μ €μž₯ν•˜λŠ” 데에 μ ν•©ν•˜λ©° μ‚¬μš©ν•˜κΈ° 쉽고 μ ‘κ·Όν•˜κΈ° λΉ λ₯Έ μž₯점이 μžˆμŠ΅λ‹ˆλ‹€.
β€’
μ €μž₯λ˜λŠ” 데이터가 μ•”ν˜Έν™”λ˜μ§€ μ•ŠμœΌλ©° 주둜 λ¬Έμžμ—΄, 숫자, λ‚ μ§œμ™€ 같은 κΈ°λ³Έ 데이터 νƒ€μž…λ§Œ μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

CoreData

β€’
μ•±μ—μ„œ λͺ¨λΈ 계측 개체λ₯Ό κ΄€λ¦¬ν•˜λŠ” 데 μ‚¬μš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬. 객체 κ·Έλž˜ν”„ κ΄€λ¦¬μžλ‘œ, 객체λ₯Ό μ§μ ‘μ μœΌλ‘œ μ—°κ²°ν•΄μ„œ κ΄€λ¦¬ν•©λ‹ˆλ‹€.
β€’
5κ°€μ§€ κΈ°λŠ₯
1.
μ˜μ†μ„±(Persistence)
2.
λ³€κ²½μ‚¬ν•­μ˜ Undo, Redo
3.
λ°±κ·ΈλΌμš΄λ“œ 데이터 μž‘μ—… κΈ°λŠ₯
4.
동기화 κΈ°λŠ₯
5.
버전 관리 및 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜(Migration)

λ°˜μ‘ν˜• ν”„λ‘œκ·Έλž˜λ°(Reactive Programming)

β€’
데이터 슀트림 λ˜λŠ” λ°μ΄ν„°μ˜ 변화에 따라 μ½”λ“œκ°€ μžλ™μœΌλ‘œ λ°˜μ‘ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„. 이 νŒ¨λŸ¬λ‹€μž„μ—μ„œλŠ” λ°μ΄ν„°μ˜ λ³€κ²½ 사항을 κ°μ§€ν•˜κ³  이에 따라 μ—°μ†μ μœΌλ‘œ λ°˜μ‘ν•˜λŠ” λ°©μ‹μœΌλ‘œ ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•©λ‹ˆλ‹€.
β€’
핡심 κ°œλ…
1.
데이터 슀트림(Data Stream): 이벀트 슀트림, κ°’μ˜ 흐름 λ“±κ³Ό 같이 μ‹œκ°„μ— 따라 μ—°μ†μ μœΌλ‘œ λ°œμƒν•˜λŠ” λ°μ΄ν„°μ˜ 흐름을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€. μ‚¬μš©μž μž…λ ₯, μ„Όμ„œ 데이터, μ™ΈλΆ€ API의 응닡 λ“± λ‹€μ–‘ν•œ μ†ŒμŠ€μ—μ„œ λ‚˜μ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.
2.
μ˜΅μ €λ²„(Observer) νŒ¨ν„΄: λ°μ΄ν„°μ˜ λ³€ν™”λ₯Ό κ°μ‹œν•˜κ³ , 변화에 따라 νŠΉμ • μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” λ””μžμΈ νŒ¨ν„΄μž…λ‹ˆλ‹€. λ³€ν™”κ°€ μΌμ–΄λ‚˜λ©΄ μ˜΅μ €λ²„λŠ” ν•΄λ‹Ή 변화에 λ°˜μ‘ν•˜μ—¬ μ•Œλ¦Όμ„ λ°›κ³ , ν•„μš”ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
3.
슀트림의 λ³€ν™˜κ³Ό μ‘°μž‘(Transforming and Manipulating Streams): 데이터 μŠ€νŠΈλ¦Όμ„ μ‘°μž‘ν•˜μ—¬ 필터링, λ§€ν•‘, κ²°ν•©, λ³€ν™˜ 등을 μˆ˜ν–‰ν•˜μ—¬ μƒˆλ‘œμš΄ μŠ€νŠΈλ¦Όμ„ μƒμ„±ν•˜λŠ” μž‘μ—…μž…λ‹ˆλ‹€. 이λ₯Ό 톡해 데이터 μŠ€νŠΈλ¦Όμ„ 효과적으둜 μ²˜λ¦¬ν•˜κ³  ν•„μš”ν•œ ν˜•νƒœλ‘œ 가곡할 수 μžˆμŠ΅λ‹ˆλ‹€.
4.
바인딩(Binding): λ°μ΄ν„°μ˜ 변화와 이에 λ”°λ₯Έ μž‘μ—…μ˜ 연결을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€. 데이터와 UI μš”μ†Œ λ˜λŠ” 데이터와 μž‘μ—… μ‚¬μ΄μ˜ 연결을 μ„€μ •ν•˜μ—¬ λ°μ΄ν„°μ˜ 변경이 λ°œμƒν•˜λ©΄ 이에 맞좰 UIλ‚˜ λ‹€λ₯Έ μž‘μ—…μ„ μžλ™μœΌλ‘œ μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€.

Combine

β€’
비동기적인 이벀트 μŠ€νŠΈλ¦Όμ„ μ²˜λ¦¬ν•˜κ³  μ‘°μž‘ν•˜λŠ” 데 μ‚¬μš©ν•˜λŠ” Swift ν”„λ ˆμž„μ›Œν¬.
β€’
ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°κ³Ό λ°˜μ‘ν˜• ν”„λ‘œκ·Έλž˜λ° κ°œλ…μ„ 기반으둜 ν•˜λ©°, 데이터 μŠ€νŠΈλ¦Όμ„ κ°„λ‹¨ν•˜κ²Œ μ‘°μž‘ν•˜κ³  μ‘°ν•©ν•  수 μžˆλŠ” 도ꡬλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.
β€’
μ£Όμš” κ°œλ…
1.
Publisher: 데이터 μŠ€νŠΈλ¦Όμ„ μƒμ„±ν•˜κ³ , 이벀트λ₯Ό λ°©μΆœν•˜λŠ” νƒ€μž…. 값을 λ°©μΆœν•  수 있으며, 였λ₯˜λ₯Ό λ°©μΆœν•˜κ±°λ‚˜ μž‘μ—…μ΄ μ™„λ£Œλ˜μ—ˆμŒμ„ μ•Œλ¦΄ 수 μžˆμŠ΅λ‹ˆλ‹€.
2.
Subscriber: Publisherμ—μ„œ λ°©μΆœλ˜λŠ” 이벀트λ₯Ό λ°›μ•„ μ²˜λ¦¬ν•˜λŠ” νƒ€μž…. 값을 λ°›μ•„ μ²˜λ¦¬ν•˜κ±°λ‚˜, 였λ₯˜λ‚˜ μž‘μ—… μ™„λ£Œ 이벀트λ₯Ό μ²˜λ¦¬ν•©λ‹ˆλ‹€.
3.
Operators: 데이터 μŠ€νŠΈλ¦Όμ„ μ‘°μž‘ν•˜κ³  λ³€ν™˜ν•˜κΈ° μœ„ν•œ λ‹€μ–‘ν•œ μ—°μ‚°μžκ°€ μ œκ³΅λ©λ‹ˆλ‹€. map, filter, flatMap λ“±μ˜ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ 데이터 μŠ€νŠΈλ¦Όμ„ μ‘°μž‘ν•˜κ³  μƒˆλ‘œμš΄ ν˜•νƒœλ‘œ λ³€ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
4.
Cancellable: ꡬ독을 μ·¨μ†Œν•  수 μžˆλŠ” νƒ€μž…. ꡬ독을 μ·¨μ†Œν•¨μœΌλ‘œμ¨ 더 이상 이벀트λ₯Ό λ°›μ§€ μ•Šλ„λ‘ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
import Foundation import Combine class DataModel { @Published var textValue: String = "" } let dataModel = DataModel() let cancellable = dataModel.$textValue.sink { newValue in print("Value changed to: \(newValue)") } dataModel.textValue = "Hello, Combine!" dataModel.textValue = "Another value" /* 좜λ ₯ Value changed to: Value changed to: Hello, Combine! Value changed to: Another value */
Swift
볡사

RxSwift

β€’
ReactiveX(Reactive Extensions) νŒ¨ν„΄μ˜ Swift λ²„μ „μœΌλ‘œ, Swift둜 μž‘μ„±λœ λ°˜μ‘ν˜• ν”„λ‘œκ·Έλž˜λ°μ„ μœ„ν•œ λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€. RxSwiftλŠ” 데이터 슀트림과 이λ₯Ό λ‹€λ£¨λŠ” μ—°μ‚°μžλ“€μ„ 톡해 비동기 및 이벀트 기반 ν”„λ‘œκ·Έλž˜λ°μ„ μ§€μ›ν•©λ‹ˆλ‹€.
β€’
μ£Όμš” κ°œλ…
1.
Observable: 데이터 μŠ€νŠΈλ¦Όμ„ λ‚˜νƒ€λ‚΄λŠ” νƒ€μž…μœΌλ‘œ, λ°μ΄ν„°μ˜ λ³€ν™”λ‚˜ 이벀트λ₯Ό 방좜(emit)ν•©λ‹ˆλ‹€. 이벀트 μ‹œν€€μŠ€λ₯Ό λ°œμƒμ‹œν‚€λŠ”λ° μ‚¬μš©λ˜κ³  이 μ΄λ²€νŠΈλŠ” next, error, completed와 같은 μ’…λ₯˜κ°€ μžˆμŠ΅λ‹ˆλ‹€.
2.
Observer: Observableμ—μ„œ 방좜된 λ°μ΄ν„°λ‚˜ μ΄λ²€νŠΈμ— λ°˜μ‘ν•˜λŠ” 객체둜, 이λ₯Ό ꡬ독(subscribe)ν•˜μ—¬ λ°μ΄ν„°μ˜ λ³€ν™”λ₯Ό κ°μ‹œν•˜κ³  μ²˜λ¦¬ν•©λ‹ˆλ‹€.
3.
Operator: Observable을 λ³€ν˜•ν•˜κ±°λ‚˜ μ‘°μž‘ν•˜λŠ” ν•¨μˆ˜λ‘œ, 데이터 μŠ€νŠΈλ¦Όμ„ μ‘°μž‘ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ©λ‹ˆλ‹€. RxSwiftμ—λŠ” λ§Žμ€ λ‹€μ–‘ν•œ μ—°μ‚°μžλ“€μ΄ ν¬ν•¨λ˜μ–΄ μžˆμ–΄μ„œ 데이터λ₯Ό ν•„ν„°λ§ν•˜κ±°λ‚˜ λ³€ν™˜, κ²°ν•©, μ‘°μž‘ν•˜λŠ” λ“±μ˜ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
4.
Schedulers: 비동기 μ½”λ“œμ˜ 싀행을 κ΄€λ¦¬ν•˜λŠ”λ° μ‚¬μš©λ˜λ©°, μž‘μ—…μ΄ μ–΄λŠ μŠ€λ ˆλ“œμ—μ„œ μ‹€ν–‰λ˜λŠ”μ§€ μ œμ–΄ν•©λ‹ˆλ‹€. 메인 μŠ€λ ˆλ“œμ—μ„œ UI μ—…λ°μ΄νŠΈλ₯Ό μˆ˜ν–‰ν•˜κ±°λ‚˜ λ°±κ·ΈλΌμš΄λ“œ μŠ€λ ˆλ“œμ—μ„œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” λ“±μ˜ 일을 μŠ€μΌ€μ€„λ§ν•  λ•Œ μ‚¬μš©λ©λ‹ˆλ‹€.
// RxSwift의 μ˜ˆμ‹œ import Foundation import RxSwift import RxCocoa class DataModel { let textValueSubject = BehaviorSubject<String>(value: "") var textValue: Observable<String> { return textValueSubject.asObservable() } } let dataModel = DataModel() let disposable = dataModel.textValue.subscribe(onNext: { newValue in print("Value changed to: \(newValue)") }) dataModel.textValueSubject.onNext("Hello, RxSwift!") dataModel.textValueSubject.onNext("Another value") /* 좜λ ₯ Value changed to: Value changed to: Hello, RxSwift! Value changed to: Another value */
Swift
볡사