apple/Docs, iOS, Swift
[iOS] SwiftData in UIKit
lgvv
2023. 12. 15. 03:05
SwiftData in UIKit
이번에는 SwiftData를 UIKit에서 사용해보자!
CoreData를 학습하기 전에는 SwiftData가 진짜 어려웠는데, 지금은 훨씬 배우기 쉽다.
SwiftData를 사용하면 CoreData와 개념적으로 부합하고 있어서 학습하는데 더 쉽게 느껴졌다.
또한 SwiftData가 가진 장점이겠지만, CoreData보다 검색이나 등등이 더 스위프트 언어와 잘 어울린다는 점.
다만 고려해야할 점으로는 @objc를 사용하는 서비스의 경우에는 도입하기가 조금 어려울 수 있다.
이번 실습 결과물 영상
- create: 아이템 추가
- read: 전체 아이템 reloadData
- update: 트리 -> 산타의 선물로 데이터 갱신
- delete: 모든 데이터 삭제
실습용 코드
//
// ThirdViewController.swift
// CoreDataExample
//
// Created by 🏝️ GeonWoo Lee on 12/15/23.
//
import UIKit
import RxSwift
import RxCocoa
import SwiftData
final class ThirdViewController: UIViewController {
/// 모델 컨테이너
var modelContainer: ModelContainer?
private var disposeBag = DisposeBag()
private func bind() {
tableView.rx.itemSelected
.bind(with: self) { this, indexPath in
print("indexPath \(indexPath)")
}.disposed(by: disposeBag)
createButton.rx.tap
.debug("createButton")
.bind(with: self) { this, _ in
let user = User(name: "🎄트리", age: 1225)
this.modelContainer?.mainContext.insert(user)
this.tableView.reloadData()
}.disposed(by: disposeBag)
readButton.rx.tap
.debug("readButton")
.bind(with: self) { this, _ in
this.tableView.reloadData()
}.disposed(by: disposeBag)
updateButton.rx.tap
.debug("updateButton")
.bind(with: self) { this, _ in
let descriptor = FetchDescriptor<User>()
let users = (try? this.modelContainer?.mainContext.fetch(descriptor)) ?? []
let filteredUsers = users.filter { $0.name == "🎄트리" }
filteredUsers.forEach { $0.name = "🎁 산타의 선물"}
try? this.modelContainer?.mainContext.save()
this.tableView.reloadData()
}.disposed(by: disposeBag)
deleteButton.rx.tap
.debug("deleteButton")
.bind(with: self) { this, _ in
let descriptor = FetchDescriptor<User>()
try? this.modelContainer?.mainContext.delete(model: User.self)
this.tableView.reloadData()
}.disposed(by: disposeBag)
}
// MARK: - Initialize
init() {
super.init(nibName: nil, bundle: nil)
configureUI()
bind()
modelContainer = try? ModelContainer(for: User.self)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - UIComponents
private lazy var tableView: UITableView = {
let tv = UITableView()
tv.delegate = self
tv.dataSource = self
return tv
}()
private lazy var container: UIStackView = {
let stackView = UIStackView()
stackView.distribution = .fillProportionally
stackView.spacing = 3
return stackView
}()
private lazy var createButton: UIButton = {
let button = makeButton("create")
return button
}()
private lazy var readButton: UIButton = {
let button = makeButton("read")
return button
}()
private lazy var updateButton: UIButton = {
let button = makeButton("update")
return button
}()
private lazy var deleteButton: UIButton = {
let button = makeButton("delete")
return button
}()
private func makeButton(_ title: String) -> UIButton {
let button = UIButton()
button.setTitle(title, for: .normal)
button.backgroundColor = .blue
button.layer.cornerRadius = 6
return button
}
private func configureUI() {
view.addSubview(container)
container.snp.makeConstraints {
$0.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
}
container.addArrangedSubview(createButton)
container.addArrangedSubview(readButton)
container.addArrangedSubview(updateButton)
container.addArrangedSubview(deleteButton)
view.addSubview(tableView)
tableView.snp.makeConstraints {
$0.top.equalTo(container.snp.bottom)
$0.leading.trailing.bottom.equalToSuperview()
}
}
}
extension ThirdViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let descriptor = FetchDescriptor<User>()
let users = (try? modelContainer?.mainContext.fetch(descriptor)) ?? []
return users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let descriptor = FetchDescriptor<User>()
let users = (try? modelContainer?.mainContext.fetch(descriptor)) ?? []
var content = cell.defaultContentConfiguration()
content.image = UIImage(systemName: "bookmark")
content.imageProperties.tintColor = .green
content.text = users[indexPath.row].name
cell.contentConfiguration = content
return cell
}
}
@Model
final class User {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
다음에는 SwiftUI에서 SwiftData를 사용하는걸 정리해보도록 하자~!