0

I want the getPhotos class method to be executed to the end, and only then the code after. Otherwise, the photos are not displayed in the collection. How can this be achieved?

// MARK: - Text Field Delegate
extension CollectionViewController: UITextFieldDelegate {

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        collectionManager.getPhotos(searchTerm: textField.text!)
        print("finish")
        self.collectionView?.reloadData()
        return true
    }
}

Implementation of the getPhotos method:

func getPhotos(searchTerm: String) -> [FlickrPhoto] {
    loader.searchFlickr(for: searchTerm) { searchResults in
        switch searchResults {
        case .error(let error):
            print("Error Searching: \(error)")
        case .results(let results):
            self.searchPhotos = results.searchResults
        }
    }
    return searchPhotos
}
Coffee inTime
  • 231
  • 1
  • 8

2 Answers2

2

you can use this closure:

func getPhotos(searchTerm: String, onCompletion: @escaping ([FlickrPhoto]) -> Void) {
        loader.searchFlickr(for: searchTerm) { searchResults in
            switch searchResults {
            case .error(let error):
                print("Error Searching: \(error)")
                onCompletion([FlickrPhoto]())
            case .results(let results):
                self.searchPhotos = results.searchResults
                onCompletion(results.searchResults)
            }
        }
        return searchPhotos
    }

and on completion call:

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
   collectionManager.getPhotos(searchTerm: textField.text!) { results 
      [weak self] in
       print("finish")
       self.searchPhotos = results
       self?.collectionView?.reloadData()
   }
   return true
}
blacker
  • 768
  • 1
  • 10
  • 13
1

You need to add a completion handler to your getPhotos method instead of the return. This is because getPhotos is asynchronous, so the completion handler is kind of what needs to be done after it finishes.

func getPhotos(searchTerm: String, completion: @escaping [FlickrPhoto]? -> ())  {
    loader.searchFlickr(for: searchTerm) { searchResults in
        switch searchResults {
        case .error(let error):
            print("Error Searching: \(error)")
        case .results(let results):
            self.searchPhotos = results.searchResults
        }
    }
    return searchPhotos
}

and then

getPhotos(searchTerm: String, completion: { _ in
   // The code inside this block will be executed when getPhotos finishes
})

However, you may not get the effect that you expect, as the return in textFieldShouldReturn will probably be executed before the completion. Can I ask what are you trying to do with this?

EDITED:

If what you want is to be sure pics have been loaded before dismissing the textfield, you can add a flag/bool in your viewController

var didLoadPics = false

and then when you add this line to your method

self.searchPhotos = results.searchResults
didLoadPics = true

so your textFieldShouldReturn would only need return didLoadPics

emelagumat
  • 301
  • 2
  • 10