iOS(Swift) -CoreData,BarButtonItem,ViewModel-[MVVM Design pattern](2)

JSLee·2021년 11월 10일
0

안녕하세유
오늘 알아볼것은!
CoreData 와~ BarButtonItem 그리구~MVVM 아키텍처에 VM을 담당하는 ViewModel까지 알아볼께유!
일단 MVVM 이 무엇인지 알아보겄습니다!!

자 ! 이런식으로 App 의 구동을 나눠 담당하는 한마디로 앱을 디자인하는 패턴 입니다!
"View" 는 정말 User의 시야에서 가장 바로 보이는 보이는 UI 적인 부분을 담당하는 곳입니다!
"ViewModel" 은 View에서 필요한 UI적 Data들의 Model들을 말해요!
"Model" 은 "ViewModel"이 "View"에게 던져줄 Data들을 가지고 있는 storage 라고 볼수 있겠습니다!
일단 그렇게 되면 View 즉 ViewController 가 상당히 가벼워집니다!
왜냐면 View의 데이터는 모두 ViewModel 이 가지고 있으니깐요 그렇기에!
ViewController 가 없어도 test가 충분히 가능하게 됩니다!
하지만!! ViewModel을 거치지 않고 Model과 View는 서로 이야기 할수없어요!
그렇기에 서로서로 연결을 시켜주는 부분이 어려운것이지유 ㅠㅠ 하지만 이렇게 따로따로 처리하기 때문에 어디서 오류가 나는지 알기 쉽고! 오류가 잘 나지 않는 설계가 가능합니다!!일단 보기 편하잖아유!ㅎㅎ

View
1. MVVM은 MVC와 달리 ViewController를 View로 취급한다.
2. 모든 UI 로직이 ViewModel에 있으므로 View/ViewController가 가벼워진다.(MVC에서보다)
3. View는 ViewModel을 참조합니다
4. View는 Model을 참조하지 않습니다
5. publication ,subscribe, observe 합니다!

ViewModel
1. MVVM은 ViewModel을 통해 UI 로직과 비즈니스 로직을 분리했다.
2. MVVM은 MVC와 달리 ViewModel이 있다.
3. ViewModel은 Model을 참조한다(반대는 X).
4. View 없이 테스트가 가능하다.
5. ViewModel은 View input으로부터 Model을 업데이트한다.
6. ViewModel은 Model이 변경되면 View에 반영한다. (Model output으로부터 View를 업데이트한다.)
7. ViewModel은 View에 직접적으로 이야기하지 않는다. 무언가 바뀌었다고 발표(publish) 한다.
9. 모든 UI 컨트롤의 상태를 알려주는 프로퍼티들을 포함한다.

Model
1. UI에 독립적이다.
2. SwiftUI나 UIKit을 import 하지 않는다.
3. App이 하는 일에 대한 데이터와 로직을 캡슐화하려고 한다.
4. Model이 변경됐을 때 ViewModel에게 알린다

자 일단 MVVM 설명은 여기까지!
일단 Data들을 보관해줄 CoreData 먼저 만들어보겠습니다!


자 이렇게 Entities 를 만들어주시고 Data들의 Type과 마지막에 옵셔널을 체크해제 하겠습니다
이제 CoreData 테이블이 정리가 되었네유!
그럼 일단 Data들을 먼저 저장하는 함수를 만들어볼께요!

CoreData를 처리해줄 Manager swift 파일을 하나 만들겠습니다!.

import CoreData
import UIKit

final class DongGangAjiCoreData {
    
    lazy var dongGangAjiPersistentContainer : NSPersistentContainer = {
        let persistentContainer = NSPersistentContainer(name: "DongGangAji")
        persistentContainer.loadPersistentStores { _, error in
            print(error?.localizedDescription ?? "")
            
        }
        return persistentContainer
    }()
    var ddong : NSManagedObjectContext {
        dongGangAjiPersistentContainer.viewContext
    }
    func ddongDataSave(name:String,date:Date,image:UIImage){
        let ddongPuppy = DongGangAji(context: ddong)
        ddongPuppy.setValue(name, forKey: "name")
        let ddongImage = image.jpegData(compressionQuality: 1)
        ddongPuppy.setValue(ddongImage, forKey: "image")
        ddongPuppy.setValue(date, forKey: "date")
        
        do {
            try ddong.save()
        }catch{
            print("😰😰😰😰😰\(error)😩😩😩😩😩 \(#line) 에러드아앙")
        }
    }
    func ddongFetch() -> [DongGangAji] {
        do {
            let ddongRequest = NSFetchRequest<DongGangAji>(entityName: "DongGangAji")
            let ddong = try ddong.fetch(ddongRequest)
            return ddong
        }catch{
            print("😰😰😰😰😰\(error)😩😩😩😩😩 \(#line) 에러드아앙")
            return []
        }
    }
}

일단 import CoreData 받아주신후에!
NSPersistentContainer 를 만들겠습니다 하지만 컨테이너는 NSManagedObjectContext 보다 늦게 생성이 되어야 하기때문에 lazy를 붙혀 주고욥

let persistentContainer = NSPersistentContainer(name: "DongGangAji")
        persistentContainer.loadPersistentStores { _, error in
            print(error?.localizedDescription ?? "")
            
        }

클로져 안에 아까 만들었던 DataModel과 연결 시켜주겠습니다

그리고

var ddong : NSManagedObjectContext {
        dongGangAjiPersistentContainer.viewContext
    }

똥옵젝컨텍스트에 똥강아지컨테이너에 연결 시켜줄께욥

func ddongDataSave(name:String,date:Date,image:UIImage){
        let ddongPuppy = DongGangAji(context: ddong)
        ddongPuppy.setValue(name, forKey: "name")
        let ddongImage = image.jpegData(compressionQuality: 1)
        ddongPuppy.setValue(ddongImage, forKey: "image")
        ddongPuppy.setValue(date, forKey: "date")
        
        do {
            try ddong.save()
        }catch{
            print("😰😰😰😰😰\(error)😩😩😩😩😩 \(#line) 에러드아앙")
        }
    }
    func ddongFetch() -> [DongGangAji] {
        do {
            let ddongRequest = NSFetchRequest<DongGangAji>(entityName: "DongGangAji")
            let ddong = try ddong.fetch(ddongRequest)
            return ddong
        }catch{
            print("😰😰😰😰😰\(error)😩😩😩😩😩 \(#line) 에러드아앙")
            return []
        }
    }
}

자 이젠 함수 입니다!!
똥데이터세이브 함수는 말그대로 파라미터를 받아 CoreData에 저장하는 함수이구요
똥패치는 리퀘스트를 받아서 데이터들을 가져오는 것입니다!
저장과 가져오는 방법은 아주간단하지요~~??
But!! do catch 는 꼭꼭 사용하셔야 합니다 ㅎㅎ!!

    private func barButtonSetUp(){
        let addImage = UIImage(systemName: "plus.circle.fill")
        let addBarButtonItem = UIBarButtonItem(image: addImage, style: .plain, target: self, action: #selector(tappedAddBarButton))
        addBarButtonItem.tintColor = .primary
        navigationItem.rightBarButtonItem = addBarButtonItem
        navigationItem.title = ddongViewModel.title
        navigationController?.navigationBar.prefersLargeTitles = true
    }

다음은~ 네비게이션바아이템 추가 방법이에요!!
요롷게 하시면 오른쪽에 버튼이 추가가 된답니다 ㅎㅎ

자 이런식으루~ CoreData 인스턴스를 하나 생성한뒤에~
아까 만든 함수를 돌려주면 로그가 잘 프린트 되는걸 확인할수 있습니다!!ㅎㅎ

감사합니다~~!!!

profile
iOS/Android/FE/BE

0개의 댓글