2017-04-26 5 views
-1

대화방 목록이있는 테이블보기가 있고 각 셀의 모든 멤버의 아바타 컬렉션보기를 얻으려고합니다. 내가 그것을 가지고각 테이블보기 셀에 다른 데이터를로드하는 방법

, 내 기능은 객실의 구성원에 대한 필요한 정보를 얻고 cellForRow에서 사전에 설정합니다

:

  DispatchQueue.main.async { 
       self.getParticipantInfo(roomId: self.usersRooms[(indexPath as NSIndexPath).row].id) 
       existingRoomCell.avatarView.addSubview((self.navCollectionView?.view)!) 
      } 

이것은 중포 기지에서 데이터를 잡아하는 기능입니다

var avatarDictionary = NSMutableDictionary() 
var statusDictionary = NSMutableDictionary() 

func getParticipantInfo(roomId: String) { 

    let databaseRef = FIRDatabase.database().reference() 

    let groupRef = databaseRef.child("groups").child(roomId) 
    groupRef.observe(.childAdded, with: { snapshot in 

     if let snapDict = snapshot.value as? [String : AnyObject] { 

      for each in snapDict { 

       let uid = each.key 
       let avatar = each.value["profilePicture"] as! String 
       let status = each.value["status"] as! String 

       // Set those to the dictionaries [UID : value] 
       self.avatarDictionary.setValue(avatar, forKey: uid) 
       self.statusDictionary.setValue(status, forKey: uid) 
       DispatchQueue.main.async { 
        self.navCollectionView?.collectionView?.reloadData() 
        print("\n\nDone\n\n") 
       } 
      } 
      print("\n\navatarDictionary:\n \(self.avatarDictionary)") 
      print("\nstatusDictionary:\n \(self.statusDictionary)") 
     } 
    }) 
} 

콘솔에 인쇄 된 각 사전 중 5 개가 표시됩니다 (현재 5 개의 회의실이 있음). 각 회의실별로 별도의 사전이있는 것 같습니다. 그러나 어떤 사전이 어느 방에 있는지 지정할 수있는 방법에 대해 고민하고 있으므로 해당 방의 멤버 만 해당 테이블 뷰 셀에 표시됩니다. 예를 들어 컬렉션 뷰의 cellForItem 방법에서

, 나는 배열에 avatarDictionary에서 모든 값을 얻어서 아바타를 설정 : 그러나 지금 여러 사전을 갖고 있기 때문에

DispatchQueue.main.async { 
     let avatars = self.roomVC?.avatarDictionary.allValues as! [String] 
     navBarCell.avatarImageView.loadImageUsingCacheWithUrlString(avatars[indexPath.row]) 
    } 

, 나는 방법을 모른다 어떤 사전이 테이블의 어느 방에 있는지 지정합니다. 현재는 단지 하나만 사용합니다. (제 생각에는) avatarDictionary입니다. 그래서 아바타는 테이블의 한 방에 나타납니다.

컬렉션보기에서 올바른 사전에서 아바타를로드하려면 어떻게해야합니까?

답변

0

Firebase 호출이 비동기이기 때문에 roomId을 tableviewcell에 전달하고 아바타와 상태를로드하는 셀 핸들을 갖는 것이 좋습니다. 예를 들어

, 일부 의사 코드 : 의견

빠른 질문에 따라

class CustomCell: UITableViewCell { 
    var roomId:String? { 
     didSet { 
      if let roomId = roomId { 
       getParticipantInfo(roomId) 
      } else { 
       //clear the data and cancel any pending Firebase request 
      } 
     } 
    } 

    func getParticipantInfo(roomId: String) { 
     //load your room, parse the data into your dictionaries and use the dictionary to power the collectionview datasource 
     collectionView.reloadData() 
    } 

    func prepareForReuse() { 
     super.prepareForReuse() 
     roomId = nil 
    } 
} 

편집 - 질문이있는 TableView를 언급하고, 변수는 collectionView입니다. 해결책은 중요하지 않지만 어느 것이지?

데이터 저장 방법에는 2 가지가 있습니다. 선택하는 방법은 실제 데이터가 어떻게 나타나는지에 달려 있습니다.

아바타/상태가 각 방마다 고유하고 섹션이 하나만 있다고 가정하면 행을 비워두기 만하면됩니다. 모든 것을 좀 더 명확하게 만들기 위해 데이터를 보관하는 구조체를 만들 것입니다. 여기에는 roomID를 담는 RowData 구조체 배열과 imageURL 및 status를 보유하는 아바타 구조체 배열이 있습니다. 이렇게하면 두 개의 병렬 배열이나 사전 정보가 명확하게 구분되지 않습니다. 내가 잘못 생각하면 나를 정정하십시오. 이제 행을 인덱스로 사용하여 아바타 데이터에 액세스 할 수 있습니다. 다른 행의 아바타 사이의 중복의 양이 많은 경우

struct Avatar { 
    var imageURL: String 
    var status: String //eventually this is better as an enum 
} 

struct RowData { 
    let roomId:String 
    var avatars = [Avatar]() 
    init(roomId: String) { 
     self.roomId = roomId 
    } 
} 

var rowData = [Int: RowData]() 

func getParticipantInfo(roomId: String, row: Int) { 
    let databaseRef = FIRDatabase.database().reference() 
    let groupRef = databaseRef.child("groups").child(roomId) 
    var thisRow = RowData(roomId: roomId) 
    rowData[row] = thisRow 
    groupRef.observe(.childAdded, with: { snapshot in 
     if let snapDict = snapshot.value as? [String : AnyObject] { 
      for each in snapDict { 
       guard let imageURL = each.value["profilePicture"] as? String, let status = each.value["status"] as? String else { continue } 
       let avatar = Avatar(imageURL: imageURL, status: status) 
       thisRow.avatars.append(avatar) 
      } 
      DispatchQueue.main.async { 
       self.navCollectionView?.collectionView?.reloadItems(at:[IndexPath(section:0, row:row)]) 
       print("\n\nDone\n\n") 
      } 
     } 
    }) 
} 

func numberOfSections(in tableView: UITableView) -> Int { 
    return 1 
} 

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return rowData.count 
} 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as RoomCell 
    if let thisRowData = rowData[indexPath] { 
     cell.rowData = rowData[indexPath.row] 
    } else { 
     getParticipantInfo(roomId: usersRooms[indexPath.row].id, row: indexPath.row) 
    } 
} 


class RoomCell: UITableViewCell, UICollectionViewDataSource { 
    var collectionView:UICollectionView 
    var rowData:RowData? { 
     didSet { 
      collectionView.reloadData() 
     } 
    } 
    func numberOfSections(in collectionView: UICollectionView) -> Int { 
     return 1 
    } 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return rowData ? rowData?.avatars.count : 0 
    } 

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCell(for: indexPath) 
     let avatar = rowData?.avatars[indexPath.row] 
    } 
} 

또는, 당신은 아바타 구조체에 var roomIds:[String] 같은 소품을 추가하고 [Avatar]의 배열을 가지고, 다음 채우는 roomId 필터링 할 수 귀하 행.이 모델의 장점은 API가 여러 행의 아바타 정보를 반환하면 여러 행에 데이터를 효과적으로 캐싱하고 아바타 객체가 중복되지 않는다는 점입니다.

+0

컬렉션보기 클래스는 테이블보기 컨트롤러의 사전을 데이터 소스 : https://pastebin.com/3ft1qS1W 대신 데이터 소스로 사용자 정의 셀을 사용할 것인가? (예 : let avatars = self.customCell? .avatarDictionary.allValues ​​as! [String] self.roomVC? .avatarDictionary.allValues ​​as! [String]') – KingTim

+0

원래 질문을 완전히 이해하지 못할 수도 있습니다. 필자는 각 tableviewcell이 고유 한 비동기 데이터 집합을 표시한다고 가정했습니다. 이게 아니라고 제안하는거야? 사전을 tableviewcontroller의 일부로 사용하는 경우 비동기 데이터를로드 한 후 데이터를 저장 한 다음 올바른 인덱스 경로에서 셀을 다시로드해야합니다. 이것이 올바른 가정이라면 샘플을 모델링 할 수도 있습니다. – dmorrow

+0

맞습니다. 각 tableview 셀은 해당 방의 멤버에 대한 아바타를 표시합니다. 'getParticipants' 함수는'roomID'를 전달 받고 해당 방의 멤버에 대한 아바타와 상태를 가져 와서 사전에 설정합니다. 이것은 내가 잃어버린 곳입니다 - 일단 그 사전이 설정되면 어떻게 프로그램이 Dict A를 셀 A의 데이터 소스로, Dict B를 셀 B의 데이터 소스로 사용 하는지를 알 수있는 방법을 확신하지 못합니다. 에. 귀하의 대답과 함께, 만약 내가 그 기능과 테이블보기 컨트롤러에서 모든 dicts을 제거하고 셀로 이동 해야하는지 잘 모르겠습니다. – KingTim