작업을 하면서 서버로부터 데이터가 읽어오고 이렇게 읽어온 데이터를 활용하여 특정 작업을 할 수 있게 해줄 필요가 있었다. 평소에는 Delegate패턴을 이용해서 처리를 해주었는데 이번 프로젝트에는 collectionViewCell 안에 CollectionView를 구성하고 또 그 CollectinView의 Cell 안에 새로운 ColletionView를 구성하고 거기에 Cell을 배치하는 좀 복잡한 view를 구성하였다. 이러한 구성에서 Delegate패턴을 활용하는게 너무 귀찮았다. 그래서 어떤 방법이 있을까 고민하다. Notification을 활용하기로했다.
1.Notification의 종류
2. Notification이란?
3.Notification의 실행로직
나는 서버로부터 데이터를 비동기적으로 받아오고 데이터를 다 받아오게 되면 mainCollectionView에 reloadData메소드를 통해 하위 CollectionView를 reload하고 데이터를 서버를 통해 들어온 데이터를 Cell에 적용 시켜줄려고한다.
class MainContainerViewController: UIViewController {
var selectedIndexPath : Int?
var sendRecentQuestionInfoArr : [QueryDocumentSnapshot]?
let maxOfRecentQuetionInerCell = 3
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(recentQuestionInfoProcess(notification:)), name: .newValueDidInput, object: nil)
defer {
DispatchQueue.global().async {
self.receivedQuetionInfoFromFireStore(numOfMaxIndex: self.maxOfRecentQuetionInerCell)
}
}
}
메인 VC에서 NotificationCenter에 Obsever를 등록하고 보내고자하는 Notification을 Post한다.
func receivedQuetionInfoFromFireStore(numOfMaxIndex: Int?){
// fireStore에서 userInfo 받아오는 로직짜기 (아직 적용 x)
var db = Firestore.firestore()
var uid = Auth.auth().currentUser?.uid
let docRef = db.collection("questions").order(by: "date", descending: true)
var recentQuestionInfosTempArr = [QueryDocumentSnapshot]()
docRef.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
// 여기서 받은 fireStore에서 Data를 이용해 notification을 만들고 notificationCenter에 post하기!
for data in 0...numOfMaxIndex!{
recentQuestionInfosTempArr.append((querySnapshot?.documents[data])!)
}
NotificationCenter.default.post(name: .newValueDidInput, object: nil, userInfo: ["data":recentQuestionInfosTempArr])
}
}
}
서버로부터 데이터를 받아오면서 데이터가 전부 들어오면 NotificationCenter로 Notification을 Post한다.
extension MainContainerViewController{
@objc func recentQuestionInfoProcess(notification: NSNotification){
guard let data = notification.userInfo?["data"] as? [QueryDocumentSnapshot] else{
return
}
print("--recentQuestionInfoProcess observer run : \(data)--")
self.sendRecentQuestionInfoArr = data
DispatchQueue.main.async {
self.mainCollectionView.reloadData()
}
}
NotificationCenter에 Notification이 들어오면 Obsever가 실행할 메소드이다. userInfo를 통해 받은 데이터를 VC에 저장하고 VC에 가장 상위 collectionView를 reloadData함으로써 하위 collectionView 및 cell들을 자동으로 reloadData하게 만들었다.
class MainContainerQuestionCollectionViewCell: UICollectionViewCell{
@IBOutlet weak var inerCollectinView: UICollectionView!
func selectedCell(indexOf: Int) {
print("delegate Test")
self.delegate?.selectedCell(indexOf: indexOf)
}
var delegate:MainContainerQuestionDelegate?
var recentQuestionInfosArrs : [QueryDocumentSnapshot]?
override func awakeFromNib() {
super.awakeFromNib()
print("-----MainContainerQuestionCollectionViewCell call awaketFromNib------")
}
}
서버에서 읽어온 데이터를 cell의 var recentQuestionInfosArrs : [QueryDocumentSnapshot]? 에 저장하도록 해주게 만들어주고 하위 Cell에 적용할 때 변수에 들어온 데이터를 이용하게 함
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainContainerQuestionContentCollectionViewCell", for: indexPath) as? MainContainerQuestionContentCollectionViewCell else {
return UICollectionViewCell()
}
let row = indexPath.row
guard var data = self.recentQuestionInfosArrs else{
print("data checking!!!")
return cell
}
if data.count == 0 {
cell.labelToHeadLine.text = ""
cell.labelToDate.text = ""
cell.labelToContents.text = ""
cell.labelToLocation.text = ""
}
else{
cell.labelToHeadLine.text = data[row]["title"] as? String ?? ""
cell.labelToDate.text = data[row]["date"] as? String ?? ""
cell.labelToContents.text = data[row]["contents"] as? String ?? ""
cell.labelToLocation.text = data[row]["questions"] as? String ?? ""
}
return cell
}
recentQuestionInfosArrs가 비어있는지 안 비어있는지 확인하고 비어있다면 기본셀을 반환하고 데이터가 들어있으면 해당 데이터를 Cell 반영할게 해주었다.
-데이터가 안들어왔을 때 기본 Cell 반환한 모습-
-데이터가 들어오면 Cell에 적용한 모습-