0

i'm new in swift and my question might be dummie for most of you. But any way i'm trying to learn by doing. Here is my problem. i have a model :

import Foundation
import Firebase

struct special {
    let name: String
    let position: Int
    let imageURL: String?
}


class SpecialList {
    
    var specialList: [special] = []

    init() {        
        
    }
    
    func loadSpecial () {
        db.collection("special").getDocuments { (querySnapshot, error) in
            if let e = error {
                print("Error\(e)")
            } else {
                if let snapshotDocuments = querySnapshot?.documents {
                    for doc in snapshotDocuments {
                        let data = doc.data()
                        if let name = data["name"] as? String, let position = data["position"] as? Int, let imageURL = data["imageURL"] as? String {
                            let newList = special(name: name, position: position, imageURL: imageURL)
                            self.specialList.append(newList)
                        }
                    }
                }
            }
        }
    }    
}

and i'm trying to implement that in ViewController:

var specialList = SpecialList()

override func viewDidLoad() {
specialList.loadSpecial()
print(specialList.specialList)
}

actually what i need is the data that that retrieves from firebase. I'm trying to save it in var specialList: [special] = []but it always empty. I think i should do something in init() but didnt found the way to do it right.

P.S. loading from firebase working fine. Checked with printing the data.

and the data should be in collectionView

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return specialList.specialList.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SpecialCell", for: indexPath as IndexPath) as! SpecialCollectionViewCell
        
        if let imageURL = specialList.specialList[indexPath.row].imageURL {
            let url = URL(string: imageURL)
            cell.specialPic.kf.setImage(with: url) // download foto
        }
        cell.specialName.text = specialList.specialList[indexPath.row].name
        return cell
    }
4
  • Set a breakpoint on self.specialList.append(newList) and check whether it called or not Commented Aug 26, 2020 at 11:27
  • inside this function its append specialList and works fine. But by implementing in ViewController it is empty. Commented Aug 26, 2020 at 11:45
  • 1
    It works asynchronously, so you have to process your data AFTER it's been loaded. Commented Aug 26, 2020 at 11:48
  • so, the problem is not in my class SpecialList? I should play around with DispatchQueue.main.async Commented Aug 26, 2020 at 13:33

3 Answers 3

1
func loadSpecial (completion: @escaping (Bool) -> Void) {
    db.collection("special").getDocuments { (querySnapshot, error) in
        if let e = error {
            print("Error\(e)")
            completion(false)
        } else {
            if let snapshotDocuments = querySnapshot?.documents {
                for doc in snapshotDocuments {
                    let data = doc.data()
                    if let name = data["name"] as? String, let position = data["position"] as? Int, let imageURL = data["imageURL"] as? String {
                        let newList = special(name: name, position: position, imageURL: imageURL)
                        self.specialList.append(newList)
                    }
                }
                completion(true)
            }
            completion(false)
        }
    }
}

add completion to Your method

and in VC do:

override func viewDidLoad() {
    super.viewDidLoad()
    specialList.loadSpecial(completion: { [weak self] success in
        self.collectionView.reloadData()
    })
}

if collection realization is right, You will see it

Sign up to request clarification or add additional context in comments.

9 Comments

inside this function its append specialList and works fine. But by implementing in ViewController it is empty.
You will see it do override func viewDidLoad() { specialList.loadSpecial() DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in print(self?.specialList.specialList) } }
now it prints result (with 3 warnings), but at the end the results should be in collection view. but there are still empty. I tried collectionView.reloadData(), but doesnt helped. i updated my question where should be stored the data at the end
an Error after updating.
but it works this way: specialList.loadSpecial { (Bool) in self.collectionView.reloadData() }
|
1

Put a breakpoint in your append statement and print statement and see which one is called first. The print statement may gets called before getting the data.

Comments

0

if someone has a same problem. The best way to solve it by using delegate. i've added extra:

protocol SpecialListUpdateDelegate {
    func didUpdate(sender: SpecialList)
}

in my class SpecialList:

var delegate: SpecialListUpdateDelegate?

in loadspecial():

self.delegate?.didUpdate(sender: self)

in VC adding protocol for VC: SpecialListUpdateDelegate

in viewDidLoad:

specialList.delegate = self

and the last implementing function:

func didUpdate(sender: SpecialList) {
        DispatchQueue.main.async {
            self.collectionView.reloadData()
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.