Как загрузить данные асинхронно из firebase и отобразить их в UICollectionView - PullRequest
0 голосов
/ 18 января 2019

Я пытаюсь отобразить имена пользователей, за которыми следует зарегистрированный пользователь. Подробно только те, у кого тоже есть история (например Snapchat) в простом UICollectionView. Поэтому мне нужно, чтобы имя пользователя этого человека отображалось в виде простой метки в этой ячейке. Чтобы получить это, я подумал, что я мог бы просто добавить всех, у кого есть история, в массив, а затем получить первый элемент для первой истории, второй элемент для второй истории и так далее ... Но, как я упоминал ранее, я хотел бы получить и отобразить имя пользователя. Проблема сейчас в том, что функция cellForItemAt не ожидает заполнения массива данными, полученными из firebase, поэтому она использует пустой массив self.storyNames, и при этом return self.storyNames.count равно 0.

class HomeViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet weak var collectionView_stories: UICollectionView!

    var storyNames: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView_stories.delegate = self
        collectionView_stories.dataSource = self
        collectionView_stories.showsHorizontalScrollIndicator = false

        getStoryNames() { storyNames in
            self.storyNames = storyNames
            DispatchQueue.main.async {
                self.collectionView_stories.reloadData()
            }
        }
    }

    @IBAction func barButton_camera_pressed(_ sender: Any) {
    }

    @IBAction func barButton_inbox_pressed(_ sender: Any) {
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.storyNames.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let story_cell = collectionView_stories.dequeueReusableCell(withReuseIdentifier: "stories_cell", for: indexPath) as? StoryCollectionViewCell

        story_cell?.imageView_story.layer.cornerRadius = (story_cell?.imageView_story.frame.size.width)! / 2
        story_cell?.imageView_story.clipsToBounds = true
        story_cell?.imageView_story.layer.shadowColor = UIColor.black.cgColor
        story_cell?.imageView_story.layer.shadowRadius = 3
        story_cell?.imageView_story.layer.shadowOpacity = 0.6
        story_cell?.imageView_story.layer.borderWidth = 1.0
        story_cell?.imageView_story.layer.borderColor = UIColor.darkGray.cgColor
        story_cell?.imageView_story.image = UIImage(named: "bitmoji")

        story_cell?.label_username.text = self.storyNames[indexPath.row]

        return story_cell!
    }

    func getStoryNames(completion: @escaping ([String]) -> ()) {
        var tempStoryNames: [String] = []
        let userID = Auth.auth().currentUser?.uid
        Database.database().reference().child("subscriptions").child(userID!).observeSingleEvent(of: .value) { snapshot in
            let dispatchGroup = DispatchGroup()
            for child in snapshot.children.allObjects as! [DataSnapshot] {
                let dict = child.value as! String
                Database.database().reference().child("users").child(dict).child("hasStory").observeSingleEvent(of: .value) { snapshot in
                    if let item = snapshot.value as? Bool {
                        if (item == true) {
                            dispatchGroup.enter()
                            Database.database().reference().child("users").child(dict).child("username").observeSingleEvent(of: .value) { snapshot in
                                let aaa = snapshot.value as! String
                                tempStoryNames.append(aaa)
                                print(tempStoryNames)
                            }
                        }
                    }
                    dispatchGroup.leave()
                }
            }
            dispatchGroup.notify(queue: .main) {
                completion(tempStoryNames)
            }
        }
    }
}

У вас есть идеи, как решить эту проблему? Я приложил все усилия и также знаю, что это не лучший код, но я работаю над этим, и поэтому мне действительно нужна ваша помощь. Я ценю каждый ответ!

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Не имеет смысла, как вы знаете , что ваш метод cellForItemAt имеет пустой массив storyNames, потому что если ваш storyNames.count равен 0, метод cellForItemAt никогда не будет достигнут. CellForItemAt вызывается только тогда, когда в этом разделе более одного элемента.

Можете ли вы установить точку останова в обработчике завершения, чтобы узнать, вернули ли вы верные storyNames?

    getStoryNames() { storyNames in
        self.storyNames = storyNames // breakpoint here to see if actual data
        DispatchQueue.main.async {
            self.collectionView_stories.reloadData() // breakpoint here to see if storyNames still empty
        }
    }

Если ваш метод cellForItemAt действительно вызывается, то я думаю, что вы должны отладить этот метод. Вы никогда не регистрируете свой идентификатор Stories_cell, так что, может быть, это может быть?

0 голосов
/ 18 января 2019

in numberOfItemsInSection Вы должны зависеть от длины storyNames, что обеспечит правильное отображение ваших данных

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return self.storyNames.count
}
...