在集合视图中有包含数据的单元格和空单元格

Posted

技术标签:

【中文标题】在集合视图中有包含数据的单元格和空单元格【英文标题】:Have cells with data and empty cells in collection view 【发布时间】:2019-11-20 03:49:07 【问题描述】:

所以我有一个集合视图,看起来像such。我在集合视图中有一组我想要的单元格,16。因此,如果没有足够的用户朋友(集合视图的数据),那么我希望 16 中的剩余单元格为空并且能够通过点击“空”单元格获得不同的功能。

编辑:

我能够修复numberOfItemsInSection 上的崩溃。我尝试做的事情,以及有些工作但不完全正确的事情,如果有多个真正的最爱,它只会显示第一个的单元格图像,但是当点击时会将我带到正确用户的视图它应该。我将实际的收藏夹附加到数组favorites,然后确定应该有的假用户数量,并将它们添加到fakeFavorites,最后将它们合并为16。发生的情况是我得到了所有的单元格,除了其中包含 2 个项目的部分显示了真实用户(数组中的第一个)

代码如下:

var favorites: [FUser] = []
var fakeFavorites: [FUser] = []
var allFavorites: [FUser] = []
@objc var favoriteId: [String] = []
var count: Int!
var remaining: Int!

let friendCellId = "friendCellID"

var user: FUser!

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
    return CGSize(width: 75, height: 75)


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets 
    if section == 0 
        return UIEdgeInsets(top: 85, left: 10, bottom: 0, right: 0)
    
    if section == 1 
        return UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
    
    if section == 2 
        return UIEdgeInsets(top: 85, left: 5, bottom: 0, right: 0)
    
    if section == 3 
        return UIEdgeInsets(top: 85, left: 20, bottom: 0, right: 0)
    
    if section == 4 
        return UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
    
    if section == 5 
        return UIEdgeInsets(top: 85, left: 5, bottom: 0, right: 0)
    
    if section == 6 
        return UIEdgeInsets(top: 85, left: 20, bottom: 0, right: 0)
    
    if section == 7 
        return UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
    
    if section == 8 
        return UIEdgeInsets(top: 85, left: 5, bottom: 0, right: 0)
    
    if section == 9 
        return UIEdgeInsets(top: 85, left: 20, bottom: 0, right: 0)
    
    if section == 10 
        return UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
    
    if section == 11 
        return UIEdgeInsets(top: 85, left: 5, bottom: 0, right: 10)
    


    return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)




func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    if section == 0  return 1 
    if section == 1  return 2 
    if section == 2  return 1 
    if section == 3  return 1 
    if section == 4  return 2 
    if section == 5  return 1 
    if section == 6  return 1 
    if section == 7  return 2 
    if section == 8  return 1 
    if section == 9  return 1 
    if section == 10  return 2 
    if section == 11  return 1 


    return allFavorites.count




func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FriendsCell


    var favorite: FUser

    if allFavorites.count == 16 
        favorite = allFavorites[indexPath.row]
        cell.bindData(friend: favorite)
        cell.profileImageView.layer.cornerRadius = 37.5
        cell.profileImageView.layer.masksToBounds = true

    

    return cell


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    let favorite = allFavorites[indexPath.row]
    if favorite.objectId == "CjEIGXRDb6hqIYDrTwBbkOlBjzR2" 
        print("Fake user! ")
     else 
        let otherProfileView = OtherProfileView()
        otherProfileView.user = favorite
        navigationController?.pushViewController(otherProfileView, animated: true)
    




func numberOfSections(in collectionView: UICollectionView) -> Int 
    return 12



func loadFavorites() 
    cleanup()


           let favoriteIds = FUser.currentUser()!.favorites

           if favoriteIds.count > 0 

               for favoriteId in favoriteIds 

                   firebase.child(kUSER).queryOrdered(byChild: kOBJECTID).queryEqual(toValue: favoriteId).observeSingleEvent(of: .value)  (snapshot) in

                       if snapshot.exists() 
                           let userDictionary = ((snapshot.value as! NSDictionary).allValues as Array).first

                           let fuser = FUser.init(_dictionary: userDictionary as! NSDictionary)

                           self.favorites.append(fuser)
                           self.favoriteId.append(fuser.objectId)
                        self.count = self.favorites.count
                        self.remaining = 16 - self.count


                        if self.remaining > 0 
                            self.createFakeUser(countFake: self.remaining)

                        
                       
                    self.friendsCollectionView.reloadData()

                   

               

            else 
               print("There are no favorites!")

           


func createFakeUser(countFake: Int) 

    let fakeUserId = "CjEIGXRDb6hqIYDrTwBbkOlBjzR2"

    firebase.child(kUSER).queryOrdered(byChild: kOBJECTID).queryEqual(toValue: fakeUserId).observeSingleEvent(of: .value)  (snapshot) in
        if snapshot.exists() 
            let userDictionary = ((snapshot.value as! NSDictionary).allValues as Array).first
            let fuser = FUser.init(_dictionary: userDictionary as! NSDictionary)
            print("How many fake users to create: \(countFake)")
            self.fakeFavorites.append(contentsOf: repeatElement(fuser, count: countFake))
            self.allFavorites.append(contentsOf: self.favorites)
            self.allFavorites.append(contentsOf: self.fakeFavorites)
            print("Total amount of all favorites: \(self.allFavorites.count)")
        
    



   @objc func cleanup() 
    favoriteId.removeAll()
    favorites.removeAll()
    fakeFavorites.removeAll()
    allFavorites.removeAll()
    friendsCollectionView.reloadData()
  '

我不确定如何解决这个问题。它看起来非常简单和接近,但我不能把手指放在它上面。如果您对我目前的工作有任何改进,请随时告诉我!

非常感谢所有帮助!

【问题讨论】:

如何使用创建一个假的 FUser 并将其添加到 self.favorites 直到获得 16 个,如果是假的,有不同的行为? @Larme 这是一个我没想到的好主意!你能提供一个例子来说明如何做到这一点吗? FUser中,添加一个属性:let isFake: Bool,和一个工厂方法:static func makeFake() -> FUser //调用一个init,你将isFake设置为true 并添加他们。 @Larme 添加新的收藏夹并因此删除/替换占位符“假”的时候,这将如何工作?您能否给出一个编码示例或回答我如何将其换掉? 【参考方案1】:

如果我正确理解您的问题,您想要做的是在您的集合视图中显示 16 个项目,并且随着新数据的进入,您想用真实的数据库条目替换空项目。如果是这样,您可以这样做:

// FUser
class FUser 
   var id: Int = 0    // Default id value for FUser
   ...

在实施此方法时需要考虑以下几点:

如果您使用的是 mysql 数据库,则 FUser 的默认 id 值可以是 0。因为 MySQL 将从 1 开始 id 并自动增加新条目的值。 如果您使用的是 Mongo DB,则 FUser 的默认 id 值可以是 ''(空字符串)。

由于每个部分的单元格数量不同,而不是使用收藏夹Array,您可以尝试使用Dictionary

// Create a favorites dictionary
var favorites: [Int: [FUser]] = [:] // key = section number, value = section items
favorites[0] = [FUser()]
favorites[1] = [FUser(), FUser()]
...

friendsCollectionView.reloadData()

现在您正在使用字典,您可以将 numberOfItemsInSection 代码替换为:

// numberOfItemsInSection
return favorites[section]!.count

此外,在cellForItemAt 函数中获取单元格的数据也变得容易得多。

// cellForItemAt
var favorite = favories[indexPath.section]![indexPath.row]

if favorite.id == 0  // This should become an empty cell
   let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "emptyCell", for: indexPath) as! EmptyCell
   // configure cell
   return cell
 else  // We got ourselves a friend, yay!
   let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FriendsCell
   // configure cell
   return cell


return cell

最后是选择部分:

// didSelectItemAt
let favorite = favorites[indexPath.section]![indexPath.row]
if favorite.id == 0 
   // Do the empty action
 else 
   // Do the friend action

因此,您可以通过收藏夹字典控制每个部分中显示的项目数量。在numberOfItemsInSection 进行更改时,您无需更改cellForRowAtdidSelectItemAt 等功能的配置。此外,由于您可以区分真实的 FUser 和虚拟的,因此您可以实现空状态操作。您唯一需要做的就是更改 favorites 字典的创建方式。在上面的代码中,我放置了虚拟 FUser 数据,而不检查 API 调用是否获取了真实的 FUsers。将该控件添加到代码中,您应该没问题。

【讨论】:

我正在使用 Firebase。这会一样吗?或者我将如何修改它来做到这一点? 它的工作原理相同,只需从 Firebase 获取您的数据并将它们添加到您想要的 favorites 这听起来正是我想要做的更彻底的研究。不过,有一件事我很困惑。您能解释一下“id”是什么以及它的作用或含义吗? 另外,为了清楚起见,使用这种方法会保持我想要的布局吗? id 是数据库中每个条目的标识符。您应该能够将FUsers 彼此区分开来。布局也将如您所愿,因为我编写的代码不会对 UI 的创建方式进行任何更改。

以上是关于在集合视图中有包含数据的单元格和空单元格的主要内容,如果未能解决你的问题,请参考以下文章

将数据从集合视图单元格内的表视图单元格传输到另一个集合视图单元格 [带图片!]

如何在xamarin中删除集合视图中的一个单元格和sqlite中的行的删除按钮?

表视图单元格和表视图标题视图的大小

如何区分用户点击我的表格视图单元格和用户点击单元格中包含的子视图?

NSTableView,多个单元格和绑定

如何在同一个xib中放置自定义单元格和表格视图?