如何在每个表视图单元格中加载不同的数据

时间:2017-04-26 17:34:59

标签: ios swift uitableview uicollectionview nsdictionary

我有一个包含聊天室列表的表格视图,我试图获取每个单元格中所有成员的头像的集合视图。

正如我所知,我的函数获取有关房间成员的必要信息,并将其设置为a { text-decoration: none !important; box-shadow: none !important; } 中的字典:

cellForRow

这是从Firebase获取数据的功能:

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

我看到每个字典中有5个打印到控制台(我目前有5个房间),所以看起来它为每个房间都有单独的字典。但是我不知道如何指定哪个词典属于哪个房间,所以只有那个房间的成员出现在相应的表格视图中。

例如,在集合视图的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)") } }) } 方法中,我通过将avatarDictionary中的所有值转换为数组来设置化身:

cellForItem

然而,由于我现在有多个词典,我不知道如何指定哪些词典适用于表格中的哪个房间。目前它只使用一个(我认为是第一个) DispatchQueue.main.async { let avatars = self.roomVC?.avatarDictionary.allValues as! [String] navBarCell.avatarImageView.loadImageUsingCacheWithUrlString(avatars[indexPath.row]) } ,因此化身只显示在表格中的一个房间。

如何让集合视图从正确的词典加载头像,而不仅仅是单个词典?

1 个答案:

答案 0 :(得分: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。解决方案并不重要,但它是哪一个?

我可以设想两种不同的方法来存储您的数据。您选择的内容取决于您的实际数据的外观。

如果每个房间的头像/状态都是唯一的,并且假设您只有一个部分,那么我们只需要关闭行。我会创建一个结构来保存您的数据,使一切更清晰。这里我有一个RowData结构数组,它包含roomId和一组Avatar结构,它们保存了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返回多行的头像信息,您实际上可以跨多行缓存数据而不会有重复的头像对象