프로그래밍/Swift
UserDefaults, FileManager, CoreData
시르베어
2025. 3. 6. 16:34
UserDefaults
UserDefaults.standard.set(_ value: Any?, forKey: String)
- 데이터를 저장, value가 Any? 이므로 원하는 데이터 아무거나 가능 UserDefaults.standard.불러올타입(forKey: String)
- 불러올 타입에 string, integer, bool 등 기본적인 타입은 대부분 가능
- 불러올 타입에 data, array 등은 중간 캐스팅 과정을 걸치거나 data로 받은 뒤 JSONDecoder().decode를 통해서 값을 변환시켜야한다.
// 데이터 저장
func saveData() {
UserDefaults.standard.set("UIKit 강의", forKey: "courseName")
print("데이터 저장 완료")
}
// 데이터 불러오기
func loadData() {
let courseName = UserDefaults.standard.string(forKey: "courseName") ?? "데이터 없음"
print("불러온 데이터: \\\\(courseName)")
}
FileManager
- JSON, 이미지, 동영상과 같은 파일을 저장하는 데 사용
- 데이터 구조를 직접 설계하고 관리해야 함
struct Note: Codable {
var title: String
var content: String
}
let fileName: String = "notes.json"
func saveNote() {
// 저장할 파일 생성
let note = Note(title: "iOS 개발", content: "FileManager 예제 학습 중")
// 데이터 저장을 위해 파일을 인코딩 - 데이터화
if let data = try? JSONEncoder().encode(note) {
// 디렉토리 생성
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// 디렉토리에 파일 경로 추가
let fileURL = documentDirectory.appendingPathComponent(fileName)
do {
// 파일 경로에 데이터화한 데이터를 작성
try data.write(to: fileURL)
print("노트 저장 성공: \\\\(fileURL)")
}catch {
print("노트 저장 실패: \\\\(error)")
}
}
}
func loadNote() {
// 디렉토리 생성
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// 디렉토리에 파일 경로 추가 - 해당 경로를 출력해서 실제로 가보면 파일이 있음
let fileURL = documentDirectory.appendingPathComponent(fileName)
// 파일 경로의 파일에서 데이터를 불러옴
if let data = try? Data(contentsOf: fileURL) {
// 데이터를 디코딩 - 원하는 타입에 대입
// 만약 불러온 값을 Note 배열에 넣고 싶다면?? .decode([Note].self, from: data)
if let note = try? JSONDecoder().decode(Note.self, from: data) {
print("불러온 노트: \\\\(note.title), \\\\(note.content)")
}
}
}
Core Data
- 데이터를 저장하고 관리하기 위한 프레임워크
- SQLite 기반이지만, 직관적인 API를 제공
- Entity, VO, DTO의 구조는 같다고 보면되지만, 사용목적(역할)에 따라서 명칭이 달라진다.
- try save() : context를 저장
- try fetch() : request에 predicate 를 같이 보낼경우 기준에 해당하는 객체 context에 반환
- "Core Data <--> Context <--> 변수" 로 이해
Q) saveData에서 context.save()를 안하면 어떻게되나!?
A) fetch에서 context의 값을 불러오기 때문에 당장은 사용이 가능하지만 어플을 껐다가 키면 저장이 안되어있기 때문에 데이터가 날라감 (항상 context.save 를 해주자!)
AppDelegate에서 컨테이너 설정을 해줘야함
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: ".xcdatamodeld 파일 이름")
container.loadPersistentStores{ storeDescription, error in
if let error = error as NSError? {
fatalError("Unresolved error \\\\(error), \\\\(error.userInfo)")
}
}
return container
}()
func saveContext() {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
}catch {
print(error)
}
}
}
데이터 저장하기
func saveData(title: String, content: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let context = appDelegate.persistentContainer.viewContext
// context에 빈 Note Entity를 생성
let note = NSEntityDescription.insertNewObject(forEntityName: "Note", into: context)
// 빈 Note Entity 값을 지정
note.setValue(title, forKey: "title")
note.setValue(content, forKey: "content")
note.setValue(Date(), forKey: "createdDate")
do {
try context.save()
print("데이터 저장 성공!")
} catch {
print("❌ 데이터 저장 실패: \\\\(error)")
}
}
데이터 불러오기
func fetchData() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let context = appDelegate.persistentContainer.viewContext
// 요청할 Entity
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Note")
do {
// 해당 Entity를 배열로 불러옴
let notes = try context.fetch(fetchRequest)
for note in notes {
// 각 애트리뷰트에 접근
let title = note.value(forKey: "title") as? String ?? ""
let content = note.value(forKey: "content") as? String ?? ""
print("📝 불러온 노트: \\\\(title) - \\\\(content)")
}
}catch {
print(error)
}
}
데이터 삭제하기
func deleteData(title: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let context = appDelegate.persistentContainer.viewContext
// 요청할 Entity
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Note")
// Entity의 조건 추가
fetchRequest.predicate = NSPredicate(format: "title == %@", title)
do {
let notes = try context.fetch(fetchRequest)
for note in notes {
// context에서 값을 삭제
context.delete(note)
}
// 변경된 context를 저장
try context.save()
}catch {
print(error)
}
}