brunch

Firebase #iOS, NewsFeed 기초

firebase, realtime database, timeline

by Tilltue

* 이글은 Swift 3.0 , Firebase 3.6.0 를 기준으로 작성되었습니다.


firebase 실시간 데이터 베이스를 뉴스피드형태로 사용하는 간단한 예제를 만들어 보려 한다.

1. 실시간으로 추가되는 데이터를 업데이트 해준다.

2. 새로고침으로 새로운 데이터를 가져온다.

3. 더 가져오기를 통해 오래된 데이터를 불러온다.

1,2 번의 경우 firebase 의 데이터베이스 이벤트를 활용하면 된다.

( childAdded,childChanged )


tumblr_n2l6x3A9hn1stn28do1_1280.png


https://brunch.co.kr/@tilltue/19

보통 feed 의 경우 날짜를 기준으로 데이터를 가져와야 하지만, 적절한 예제json 이 없어서

이 글에서 사용한 프로젝트를 활용하려 한다.

날짜 대신에 기본 key 값으로 활용하려 한다.

스크린샷 2016-10-16 오후 6.00.49.png



테이블 refresh, load more 를 UI로 표현해줄 오픈소스를 하나 추가한다.

pod 'PullToRefresher', '~> 2.0'

https://github.com/Yalantis/PullToRefresh


ViewController 에 아래의 코드를 추가하자.


import PullToRefresh
...

class ViewController: UIViewController {
@IBOutlet fileprivate weak var tableView: UITableView!
var ref: FIRDatabaseReference? = nil
var cards = [Card]()
let refresher = PullToRefresh()

deinit {
tableView.removePullToRefresh(tableView.bottomPullToRefresh!)
tableView.removePullToRefresh(tableView.topPullToRefresh!)
}
override func viewDidLoad() {
super.viewDidLoad()
//... 초기 데이터 15개를 불러오는 코드
self.ref = FIRDatabase.database().reference()
guard let ref = self.ref else { return }
let query = ref.child("Cards").queryLimited(toFirst: 15)
query.observeSingleEvent(of: .value, with: { [weak self] snapshot in
guard let wself = self else { return }
print(snapshot.value)
for childSnapshot in snapshot.children {
if let childSnapshot = childSnapshot as? FIRDataSnapshot {
let card = Card(snapshot: childSnapshot)
wself.cards.append(card)
}
}
wself.tableView.reloadData()
})
removeEventHandler(ref: ref)
setupPullToRefresh()
}
}
fileprivate extension ViewController {
func moreLoading() {
if let ref = self.ref, let lastCard = cards.last {
let key = String((Int(lastCard.ref.key) ?? 0) + 1)
let query = ref.child("Cards").queryOrderedByKey().queryStarting(atValue: key).queryLimited(toFirst: 3)
query.observeSingleEvent(of: .value, with: { [weak self] snapshot in
guard let wself = self else { return }
for childSnapshot in snapshot.children {
if let childSnapshot = childSnapshot as? FIRDataSnapshot {
let card = Card(snapshot: childSnapshot)
wself.cards.append(card)
}
}
wself.tableView.reloadData()
wself.tableView.endRefreshing(at: .bottom)
})
}else{
//Failed
self.tableView.endRefreshing(at: .bottom)
}
}

현재 가진 카드 객체중 마지막 객체의 키값에 1을 더해서 그때부터 데이터를 3개 더 가져오는 코드이다.

let key = String((Int(lastCard.ref.key) ?? 0) + 1)

let query = ref.child("Cards").queryOrderedByKey().queryStarting(atValue: key).queryLimited(toFirst: 3)



하단 refresh 시 moreloading 함수를 호출하도록 하자.

func setupPullToRefresh() {
tableView.addPullToRefresh(PullToRefresh()) { [weak self] in
let delayTime = DispatchTime.now() + Double(Int64(2 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: delayTime) {
}
}
tableView.addPullToRefresh(PullToRefresh(position: .bottom)) { [weak self] in
let delayTime = DispatchTime.now() + Double(Int64(2 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: delayTime) {
self?.moreLoading()
}
}
}
}
Simulator Screen Shot 2016. 10. 16. 오후 6.21.57.png

위와 같이 3개씩 다음 아이템을 불러오는 것을 확인 할 수 있다.


업데이트 될때를 위한 코드를 작성해보자.

func changeEventHandler(ref: FIRDatabaseReference){

_ = ref.child("Cards").observe(.childChanged, with: { [weak self] snapshot in

print("change!!")

print(snapshot.value)

guard let wself = self else { return }

let card = Card(snapshot: snapshot)

if let updateIndex = wself.cards.index(of: card) {

wself.tableView.beginUpdates()

wself.cards[updateIndex] = card

wself.tableView.reloadRows(at: [IndexPath(row: updateIndex, section: 0)], with: .none)

wself.tableView.endUpdates()

}

})

}

콘솔에서 카드 내의 name 을 바꿔서 현재 보고있는 테이블의 이름이 변경되는지 확인해보자.



keyword
매거진의 이전글Firebase, #iOS 클라우드메시지