https://clamp-coding.tistory.com/entry/Use-Firebase-IOS
파이어베이스와 연결해준다 상단링크.
파이어 베이스의 RealtimeDatabase
https://clamp-coding.tistory.com/entry/IOS-Firebase-Realtime-Database
데이터베이스 만들기.
공부하는 용도의 경우 기본 데이터베이스 옵션 설정,
데이터 베이스가 생성되었다.
데이터를 추가하는 방법
1.
2. 메뉴의 JSON 가져오기
Pod FIle 설정
코코아팟을 활용하여 추가한다.
1. 프로젝트가 있은 폴더를 우클릭, 폴더에서 새로운 터미널 열기
2. 터미널 창에서 pod init을 입력하고 엔터를 누르고 폴더에 들어가면 podfile이 만들어져있다.
3. podfile을 열어서 pod 'Firebase/Database' 입력
# Pods for 프로젝트이름
pod 'Firebase/Database'
3. 터미널로 돌아가서 pod install
m1맥이고 오류가 난다면
$ sudo arch -x86_64 gem install ffi
$ arch -x86_64 pod install
4. xcworkspace로 작업한다.
5. command + b를 눌러 빌드해준다
6. 사용할 위치와 AppDelegate에서 import FirebaseDatabase를 해준다.
7. AppDelegate의 didFinishLaunchingWithOptions에서 FirebaseApp.configure()를 해준다.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
return true
}
데이터 베이스 읽기
1. DatabaseReference! 객체 = Firebase Realtime database 를 가져올수있는 레퍼런스 객체
var ref: DatabasReferencd!
Realtime Database의 Root레퍼런스에 접근.
ref = Database.database().reference() 라고 선언을 해주면 firebase가 우리의 database를 잡아내고 앞으로 만든 데이터 흐름들을 주고 받게 된다.
2.
ref.observe(.value) { snapshot in
guard let value = snapshot.value as? [String: [String: Any]] else { return }
}
만들어준 ref가 observe(바라본다)한다, 무엇을? .value를
바라본 다음엔 snapshot이 발생되는데, value는 snapshot의 value이다.
어떤 형태일 것인가, 여기엔 각자가 만들어둔 자료형을 건네주면 되는데 난 딕셔너리타입의 [String: [String: Any]를 만들어놨다.
이러한 value값이 아니라면 return 한다.
3.
do{
}catch let error{
print("ERROR Json parsing \(error.localizedDescription)")
}
JSON형태로 받아오기 때문에 받아온 후에는 JSONDecoding을 해주어야함 (JSON데이터를 만들어둔 구조체에 대입해야함.)
JSONDecoding은 do catch문으로 하는데 error가 발생할 경우(error)가 잡힐 경우 에러처리를 해줌.
4.
let jsonData = try JSONSerialization.data(withJSONObject: value)
let cardData = try JSONDecoder().decode([String: CreditCard].self, from: jsonData)
JSONDecoding 과정
JsonData 는 JSONSerialization을 통해 JSON을 받는데, JSONObject는 위에서 만든 value값이며,
catdData는 어떤 형태일 것이냐.
JSONDecoder를 통해서, decode한다.
우리가 만들것은 [String: CreditCard]형태일 것이기 떄문에 [String: CreditCard].self가 되며
위에서 받아온 jsonData를 넣어준다
5.
let cardList = Array(cardData.values)
self.creditCardList = cardList.sorted{ $0.rank < $1.rank }
decode가 된 값들을 이제 배열 형태로 저장해준다.
cardList는 Array가 될 것이고 그 값은 cardData의 values값들이다 (딕셔너리타입으로 받아왔기때문에 value만 가 져감)
미리 만들어놓은 creditCardList에 cardList를 넘겨주는데 정렬을 해서 순위별로 보여지게 해줌.
실시간 데이터 베이스는 스냅샷이란것을 이용해서 데이터를 불러온다.
레퍼런스에서 값을 지켜보고 있다가, 값을 스냅샷이라는 객체로 전달하게 된다.
우리는 이 객체를 클로저 안에서 잘 가공해서 이용하면 된다.
전달되는 스냅샷에서 value는 우리가 이해하고있는 데이터베이스의 자료구조를 지정해주는것.
여기서 이 타입을 정확하게 ([String: [String: Any]) 지정해주지 않으면 데이터베이스는 스냅샷에서 전달받은 데이터를 이해하지 못해서 nil을 방출하게된다. 제대로 전달 받았다면 Codable의 Decoder를 통해서 기존에 만들어 두었던 객체로 만들어 줄 수 있다
후 전달을 잘 받았다면 UI컴포넌트들을 reloadData()해주어야 데이터가 잘 표현된다
이 메서드는 UI를 표현하는 것으로 메인 스레드에서 작동해야한다.
DispatchQueue.main.async{ }로 메인스레드에서 작동하게 해줄 수 있다.
데이터 쓰기
데이터를 쓸때엔 레퍼런스에서 어떤 경로에 입력할지를 알아야함.
데이터의 구조에 따라 이 경로를 알 수도있고 모를 수도 있다.
데이터를 쓸 때엔 데이터를 쓸 액션이 일어나는 곳으로 간다
1.
let cardID = creditCardList[indexPath.row].id
ref.child("Item\(cardID)/isSelected").setValue(true)//쓰기에서 생성했던 ref레퍼런스
database엔 isSelected라는 데이터를 저장할 수 있는 공간이 있다.
ref에 child에 Path를 추가할 수 있는데 Path(경로) 라는 곳에 setValue를 할 수 있다.
2. 만약 경로를 모를경우 하나의 값에대한 경로를 얻어와야한다.
ref.queryOrdered(byChild: "id").queryEqual(toValue: cardID).observe(.value) { [weak self] snapshot in
guard let self = self,
let value = snapshot.value as? [String: [String: Any]],
let key = value.keys.first else { return }
self.ref.child("\(key)/isSelected").setValue(true)
}
데이터 삭제
데이터 삭제는 nil값을 쓴다는 것에 쓰기와 동일하다.
삭제는 아무것도 없는값을 쓰는다.
하지만 firebase에서는 삭제를 좀 더 명시화 하는 removeValue 메서드를 제공한다.
방식은 쓰기와 동일하다.
경로를 알 때와 모를 때
두가지 방식이 있다.
하지만 쓰기에서 .setValue 대신 .removeValue를 쓴다는건 동일하다.