Search code examples
iosarraysswiftviewdidload

Why it print out an empty array instead of the array appended with values for the first time in viewDidLoad()?


I'd like to have an array appended with values from database in viewDidLoad() so that I can extract a value and assign it to an UILabel.text after loading the view.

The codes:

var tagArr = [Tag]()

  

          override func viewDidLoad() {
                super.viewDidLoad()
        
        let AA = fetchTagPool()
        print(AA)
        
                
            }

 

   func fetchTagPool() -> [Tag]{
      
        API.Tag.observeTagPool {(tag) in
            self.tagArr.append(tag)
            print(self.tagArr)
        }

        return self.tagArr
    }

The result of print(AA) is an empty array as [] while that of print(self.tagArr) is the expected array appended with value from database.

How do I fix the code to make print(AA) work as print(self.tagArr) does?

Many thanks


Solution

  • The call to API.Tag.observeTagPool is asynchronous and it will finish after fetchTagPool() has returned the empty self.tagArr.

    You need to change fetchTagPool to return the value through a callback function like this:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Note: This will print AA after viewDidLoad finishes
        // Use trailing closure syntax to pass the trailing closure
        // as "callback".  Then fetchTagPool calls "callback", this
        // closure will receive the value as AA and print it and
        // update the UILabel
        fetchTagPool() { AA in
            print(AA)
    
            // Use value to update a label
            myLabel.text = AA[0].name
        }
    
        print("This will print first")
    }
    
    func fetchTagPool(callback: ([Tag]) -> Void) {
          
        API.Tag.observeTagPool { tag in
            self.tagArr.append(tag)
            print(self.tagArr)
            callback(self.tagArr)
        }
    
    }
    
    

    If your API.Tag.observeTagPool runs on a background queue and doesn't return to the main queue to return its value, you should move to the main queue before updating the value in your property like this:

    func fetchTagPool(callback: ([Tag]) -> Void) {
          
        API.Tag.observeTagPool { tag in
            DispatchQueue.main.async {
                self.tagArr.append(tag)
                print(self.tagArr)
                callback(self.tagArr)
            }
        }
    
    }