在使用Firebase的UICollectionView中填充图片时,如何组织数据

时间:2018-10-25 12:54:39

标签: ios firebase uicollectionview

我是Swift的新手,通常是进行编码,并且一直在一个项目中工作,我想创建一个UICollectionView,其中填充了Firebase中的图像。

UICollectionView的每个部分都是一个类别,并且每个类别都将包含与该类别相关的图像。每个UICollectionView都属于一个父对象,我需要跟踪哪个父对象具有哪些类别以及每个类别中的图像。

要跟踪父级,类别和图像,我以以下方式设置了Firebase数据库(碗为父级,水果名称为类别,而键是对存储在其他位置的图像数据的引用数据库):

"bowl" : {
        "apple" : {
            "-LOM1R4EH9nszjJp0Va5" : true,
            "-LOM1aRZT2XCE-6fvLBK" : true,
            "-LOM1hSTmRY6wGrWMvIo" : true,
            "-LOM1xnvKE6lc7fizomh" : true
        },
        "banana" : {
            "-LOLmQWLXXyiCUwDBwID" : true
        },
        "pear" : {
            "-LOLHakW-EtqevCeHfzl" : true,
            "-LOM2DBGGuX5VQLmBz46" : true
        },
        "orange" : {
            "-LOM26_pm6lbJ1D6hVPB" : true
        }
    }

数据库的图像数据部分如下所示:

    "image" : {
        "fruit" : {
            "-LOLHakW-EtqevCeHfzl" : {
                "description" : "round orange",
                "imageURL" : "https://firebasestorage.googleapis.com/1/image1"
            },
            "-LOLmQWLXXyiCUwDBwID" : {
                "description" : "big banana",
                "imageURL" : "https://firebasestorage.googleapis.com/1/image2"
            },
            "-LOM1R4EH9nszjJp0Va5" : {
                "description" : "small apple",
                "imageURL" : "https://firebasestorage.googleapis.com/1/image3"
            }
        }
    }

我一直在尝试的方法是创建一个带有图像键的字典,然后遍历图像键以获取与每个键关联的图像数据(例如imageURL),然后使用imageURL下载图像并填充UICollectionView。

我创建了一个结构,如下所示来转换图像数据:

struct FruitPicture {
        let imageURL: String
        let description: String
        init(imageURL: String, description: String) {
            self.imageURL = imageURL
            self.description = description
        }
        init?(snapshot: DataSnapshot) {
            guard
                let value = snapshot.value as? [String: AnyObject],
                let imageURL = value["imageURL"] as? String,
                let description = value["description"] as? String else {
                    return nil
            }
            self.imageURL = imageURL
            self.description = description
        }
        func toAnyObject() -> Any {
            return [
                "imageURL": imageURL,
                "description": description
            ]
        }
    }

我已经能够收集imageURL并填充UICollectionView,但其中不包括类别详细信息,到目前为止,它涉及通过快照,字典,数组,字典数组和如此反复,从一种配置转换为另一种配置,然后又回到另一种配置,现在我变得困惑不解。

我已经开始考虑使用多个结构并将一个结构嵌套在另一个结构中,但我对此一无所知,并且花了很多时间无所作为:

struct Picture {
    var url: URL
    var image: UIImage?
}

struct PictureCategory {
    var name: String
    var pictures: [Picture]
}

我希望能获得一些建议或路线图,或者您将如何实现此目标的细节,或者一些示例代码,或者任何能使我朝着正确方向指出的东西。谢谢。

编辑以添加更多信息

谢谢Iraniya,您的回复非常有帮助,并以不同的方式帮助我考虑问题。

根据您的建议,我编写了以下内容,其中查找保龄球将创建其中的图像元数据的快照(例如,水果和与该水果相关的键),然后使用这些键来创建图像数据的快照(例如键,imageURL,描述)。然后,我将两个快照都转换成字典,然后将字典返回到调用它的方法中:

// GET DATA
static func getPicData(forKey bowlKey: String, completion: @escaping ([String : [Any]], [String : [FruitPicture]]) -> Void) {

    var imageMetaDict: [String : [Any]] = [:]
    var imageDataDict: [String : [FruitPicture]] = [:]

    // DEFINE DATABASE TARGET
    let ref = Database.database().reference().child("meta").child("bowl").child(bowlKey).child("fruit")

    // GET DATA INTO SNAPSHOT AND TRANSFORM INTO DICTIONARY
    ref.observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dict = snapshot.value as? [String:[String:Any]] else {
            return completion([:],[:])
        }

        // DEFINE DISPATCH GROUP
        let dispatchGroup = DispatchGroup()

        // ITERATAE THROUGH DICTIONARY
        for (categoryObject, fruitData) in dict {

            // CREATE ARRAY TO STORE ITEMS
            var itemArray = [String]()

            // ITERATE THROUGH ITEMS IN FRUIT DATA
            for item in fruitData {

                // APPEND ITEM.KEY TO ITEM ARRAY
                itemArray.append(item.key)

                // ENTER DISPATCH GROUP
                dispatchGroup.enter()

                // USE ITEM.KEY TO GATHER IMAGE DATA
                Service.viewPicData(forKey: item.key) { (fruitItem) in
                        if let fruitItem = fruitItem {
                            imageDataDict[item.key] = [fruitItem]
                        }
                    // EXIT DISPATCH GROUP
                        dispatchGroup.leave()
                    }
            }

            // STORE ARRAY IN DICTIONARY UNDER FRUIT CATEGORY KEY
            imageMetaDict[categoryObject] = itemArray

        }

        // RETURN COMPLETION
        dispatchGroup.notify(queue: .main, execute: {
            completion(imageMetaDict, imageDataDict)
        })
    })
}

每本字典看起来都类似于以下内容:

imageMetaDict

[
"apple": ["-LOM1R4EH9nszjJp0Va5", "-LOM1xnvKE6lc7fizomh", "-LOM1hSTmRY6wGrWMvIo", "-LOM1aRZT2XCE-6fvLBK"],
"pear": ["-LOLHakW-EtqevCeHfzl", "-LOM2DBGGuX5VQLmBz46"], 
"banana": ["-LOLmQWLXXyiCUwDBwID"], 
"orange": ["-LOM26_pm6lbJ1D6hVPB"]
]

imageDataDict

 [
 "-LOM26_pm6lbJ1D6hVPB": [myApp.FruitPicture(imageURL: "https://firebasestorage.googleapis.com/1/image1", description: "pear 1")],
 "-LOM2DBGGuX5VQLmBz46": [myApp.FruitPicture(imageURL: "https://firebasestorage.googleapis.com/1/image2", description: "banana 1")],
 "-LOLmQWLXXyiCUwDBwID": [myApp.FruitPicture(imageURL: "https://firebasestorage.googleapis.com/1/image3", description: "apple 1")]
 ]

这与您的建议是否在正确的轨道上?

据我了解,下一步是:

  1. 创建一个按字母顺序排序的fruit.keys数组
  2. 使用fruit.keys从'imageMetaDict'获取image.keys
  3. 使用这些image.keys在“ imageDataDict”中查找图像数据(imageURL等)
  4. 将所有这些数据转换为一个新的FruitDict,其中包含fruitCategory-> [fruitObject]

这与您的建议相似吗?我很高兴听到您有任何进一步的指针,代码或建议,到目前为止,您确实对我有帮助!

1 个答案:

答案 0 :(得分:0)

要存储图像,请使用从image->> fruits中的Firebase密钥获得的密钥创建imageDict哈希图(字典),例如:“-LOLHakW-EtqevCeHfzl”,其值为您要获取的值或已经创建的结构,现在是填充水果->苹果从碗形数组或dict中获取键,然后使用相同的键从imagesDict dict(您刚才创建的哈希图

现在在将数据存储在Firebase中时,请确保每个图像都有唯一的键并将相同的键存储在您的碗中-> apple-> image,这样可以快速,轻松地管理图像数据和水果数据,使用存储新图像时获得的密钥:-)如果您喜欢我可以在更多部门解释的解决方案:-) #HappyCoding

示例

firebase节点

"bowl" : {
        "apple" : {
            "-LOLHakW-EtqevCeHfzl" : true,
            "--LOLmQWLXXyiCUwDBwID" : false,
        }
    }


"image" : {
        "fruit" : {
            "-LOLHakW-EtqevCeHfzl" : {
                "description" : "round orange",
                "imageURL" : "https://firebasestorage.googleapis.com/1/image1"
            },
            "-LOLmQWLXXyiCUwDBwID" : {
                "description" : "big banana",
                "imageURL" : "https://firebasestorage.googleapis.com/1/image2"
            }
        }
    }

ImageDict

"-LOLHakW-EtqevCeHfzl":{
                        "description" : "round orange",
                        "imageURL" : "https://firebasestorage.googleapis.com/1/image1"
                       },
 "-LOLmQWLXXyiCUwDBwID" : {
                        "description" : "big banana",
                        "imageURL" : "https://firebasestorage.googleapis.com/1/image2"
                    }

{"-LOLHakW-EtqevCeHfzl":imageStruct1,
"-LOLmQWLXXyiCUwDBwID" :imageStruct2}

现在在填充苹果时显示图像

var keys = boul["apple"].allKeys;
if(boul["apple"][keys[0]]){ //value is true show image 
  var imageUrl = imageDict[keys[0]["imageURL"]; //if using dict
  //or
  var image = imageDict[key[0]].imageURL //if using struct

}

现在要存储父级,类别以及其中的图像详细信息 创建一个名为FruitsDict的Dict或其他在dict旁边带有dict的字典,例如:“ apple”:{apples详细信息,例如图像价格等},但是如果您只想存储图像,则只需创建具有真实价值的图像列表即可例如:“ apple”:[key1,key2 ...]; (您从imageDict获得的键。

现在根据您的要求

  1. 显示所有类别!然后从fruitDict创建所有类别,并将其用作数据源 并使用imageDict和fruitsDict获取详细信息
  2. 仅显示特定类别(例如基于时令水果的类别),然后创建这些水果的列表并显示基于imageDict和fruiteDict的类别

    HappyCoding:-)