I finally manage how to get the information I wanted, with the help of DispatchGroup to make sure every pieces of info were there before doing some actions.
So main difference between the code above the following one, it's the order of the actions that changed everything. So in my old code, I used to ask for a refresh of my tableView and in that refresh function, then call the Youtube API. That setup brought me into a bottleneck. So after some advices (thank you guys!) I decided to first call the API and store result in a new array. Once everything was there (with the help of DispatchGroup), I would then refresh the tableView with the data of the fresh new array.
So here is (most of) the new code of my different functions (some are linked to buttons or other stuff on the UI):
let youtubeUrl = "https://www.googleapis.com/youtube/v3/videos?part=contentDetails%2C+snippet%2C+statistics&id="
//"AKiiekaEHhI&key="
var youtubeUrlForRequest:String = ""
let dispatchGroup = DispatchGroup()
var test_title: Array<String> = []
//func
@IBAction func plus(_ sender: NSButton) {
if urlInput.stringValue == "" {
} else {
if valeurEndroit.indexOfSelectedItem == -1{
print("coucou!")
test_text = urlInput.stringValue
test_data.append(test_text)
dispatchGroup.enter()
fetchData2(lien: test_data.last!, userCompletionHandler: {data_y, user_y, error_y in
if let user_y = user_y{
self.test_title.append(user_y)
self.dispatchGroup.leave()
}
})
dispatchGroup.notify(queue: .main) {
//print(untitle)
print("J'ai fini la liste de titre. Voici la liste: ")
//print(self.test_title)
self.urlInput.stringValue = ""
print(self.test_title)
self.tableView.reloadData()
}
//tableView.reloadData()
}else{
if valeurEndroit.indexOfSelectedItem >= test_data.count{
test_text = urlInput.stringValue
test_data.append(test_text)
dispatchGroup.enter()
fetchData2(lien: test_data.last!, userCompletionHandler: {data_y, user_y, error_y in
if let user_y = user_y{
self.test_title.append(user_y)
self.dispatchGroup.leave()
}
})
dispatchGroup.notify(queue: .main) {
//print(untitle)
print("J'ai fini la liste de titre. Voici la liste: ")
//print(self.test_title)
self.urlInput.stringValue = ""
print(self.test_title)
self.tableView.reloadData()
}
}else{
var y_index = (valeurEndroit.indexOfSelectedItem)
test_text = urlInput.stringValue
test_data.insert(test_text, at: valeurEndroit.indexOfSelectedItem)
dispatchGroup.enter()
fetchData2(lien: test_data[y_index], userCompletionHandler: {data_y, user_y, error_y in
if let user_y = user_y{
self.test_title.insert(user_y, at : y_index)
self.dispatchGroup.leave()
}
})
dispatchGroup.notify(queue: .main) {
//print(untitle)
print("J'ai fini la liste de titre. Voici la liste: ")
//print(self.test_title)
self.urlInput.stringValue = ""
print(self.test_title)
self.tableView.reloadData()
}
}
}
// fonction du bouton +
}
}
@IBAction func nextLien(_ sender: NSButton) {
if test_data == [] {
} else {
nextUrl=test_data[0]
var monUrl = URL(string: nextUrl)
var maRequete = URLRequest(url: monUrl!)
view_web.load(maRequete)
test_data.remove(at: 0)
test_title.remove(at: 0)
tableView.reloadData()
//fonction du bouton pour le prochain lien
}
}
@IBAction func openUnFichier(_ sender: NSMenuItem) {
let fichierPanel: NSOpenPanel = NSOpenPanel()
fichierPanel.allowsMultipleSelection = false
fichierPanel.canChooseFiles = true
fichierPanel.canChooseDirectories = false
fichierPanel.allowedFileTypes = ["txt"]
let response = fichierPanel.runModal()
if response == NSApplication.ModalResponse.OK{
guard let selectedURL = fichierPanel.url else{return}
do{
var fullDocument = try String(contentsOf: selectedURL, encoding: String.Encoding.utf8)
var lines : [String] = fullDocument.components(separatedBy: "\n" as String)
for line in lines {
test_data.append(line)
dispatchGroup.enter()
fetchData2(lien: test_data.last!, userCompletionHandler: {data_y, user_y, error_y in
if let user_y = user_y{
self.test_title.append(user_y)
self.dispatchGroup.leave()
}
})
dispatchGroup.notify(queue: .main) {
//print(untitle)
print("J'ai fini la liste de titre. Voici la liste: ")
//print(self.test_title)
self.urlInput.stringValue = ""
print(self.test_title)
self.tableView.reloadData()
}
}
} catch let error as NSError{
print("Erreur!!!!!!! \(error)")
}
//tableView.reloadData()
}else {
}
}
func numberOfRows(in tableView: NSTableView) -> Int {
return test_title.count
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
return (test_title[row])
}
func fetchData2(lien: String, userCompletionHandler: @escaping (String?, String?, Error?) -> Void){
var titleLien: String = ""
var urlToExtract_y = lien
var videoID_y = urlToExtract_y.components(separatedBy: "=")[1]
var youtubeUrlForRequest_y = youtubeUrl + videoID_y + "&key=" + youtubeApiKey
print(youtubeUrlForRequest_y)
var Url_y = URL(string: youtubeUrlForRequest_y)
var titleVideo_y = ""
let task_y = URLSession.shared.dataTask(with: Url_y!) { (data_y, response, error_y) in
do {
if let jsonResult_y = try JSONSerialization.jsonObject(with: data_y!, options: JSONSerialization.ReadingOptions.allowFragments) as? [String : AnyObject] {
if var items_y = jsonResult_y["items"] as? [AnyObject]? {
var snippetDict_y = items_y?[0]["snippet"] as! [String: AnyObject]
var titleVideo_y = snippetDict_y["title"] as! String
userCompletionHandler(titleVideo_y, titleVideo_y, nil)
}
}
}
catch {
print("json error: \(error_y)")
}
}
task_y.resume()
}
//var Outlet
@IBOutlet weak var urlInput: NSTextField!
@IBOutlet weak var view_web: WKWebView!
@IBOutlet weak var tableView: NSTableView!
@IBOutlet weak var valeurEndroit: NSComboBox!
Some parts has not been paste here because it's not important for the comprehension or it's sensitive (Youtube API Key for example).