Я, наконец, могу узнать, как получить нужную информацию, с помощью DispatchGroup, чтобы убедиться, что все фрагменты информации были там, прежде чем выполнять какие-либо действия.
Итак, главное отличие кода выше следующего - это порядок действий, которые все изменили. Поэтому в моем старом коде я обычно запрашивал обновление моего tableView и в этой функции обновления, а затем вызывал API YouTube. Эта установка привела меня в узкое место. Поэтому после некоторых советов (спасибо, ребята!) Я решил сначала вызвать API и сохранить результат в новом массиве. Как только все будет доступно (с помощью DispatchGroup), я обновлю tableView данными нового нового массива.
Итак, вот (большая часть) новый код моих различных функций (некоторые из них связаны с кнопками или другими элементами пользовательского интерфейса):
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!
Некоторые части здесь не вставлены, потому что это не важно для понимания или чувствительно (например, ключ API Youtube).