无法从外部userCompletionHandler访问值

时间:2019-06-01 14:42:09

标签: swift

我正在使用API​​(更准确地说是Youtube API ...)来获取视频标题。

因此,我基本上创建了一个函数来调用API并获得所需的答案。之后,我希望能够得到该结果并将其返回到tableCellView中。

获取信息很好,一切正常。 但是当我想获取信息并返回它时,就会出现问题。

这是我的功能:

next.config.js

所以上面的那部分很好。

这是我调用函数的方式:

func fetchData(userCompletionHandler: @escaping (String?, Error?) -> Void){
    var yUrl = URL(string: youtubeUrlForRequest)
    let task = URLSession.shared.dataTask(with: yUrl!) { (data, yresponse, yerror) in
        do {
            if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as? [String : AnyObject] {

                if var items = jsonResult["items"] as? [AnyObject]? {
                    var snippetDict = items?[0]["snippet"] as! [String: AnyObject]
                    var titleVideo = snippetDict["title"] as! String
                    userCompletionHandler(titleVideo, nil)
                }
            }
        }
        catch {
            print("json error: \(error)")
        }
    }
    task.resume()

}

所以fetchData ( userCompletionHandler: { (ytitle, yerror) in //var untitre = "" guard let untitle = ytitle else{ print("Ok I'm in!!!") //untitle = ytitle //print(untitle) return } print("OK HERE!!!!!!!!") print(untitle) }) //var test_titre = "Le titre est: " + bontitre print(untitle) return () 下的print(untitle)很好,我确实得到了想要的数据。

但是print("OK HERE!!!!!!!")上的print(untitle)不会显示相同的内容。它将在上面创建时显示我给return()赋予的值:

untitle

我的目标是使var untitle: String = "a" 的视频标题现在return(untitle)处。

1 个答案:

答案 0 :(得分:0)

在DispatchGroup的帮助下,我终于设法获得所需的信息,以确保在执行某些操作之前,每条信息都在那里。

因此,下面的代码之间的主要区别是,更改所有内容的操作顺序。因此,在我的代码中,我曾经要求刷新tableView和该刷新功能,然后调用Youtube API。这种设置使我陷入瓶颈。因此,在提出了一些建议之后(谢谢大家!),我决定首先调用API并将结果存储在新数组中。一旦一切就绪(在DispatchGroup的帮助下),我将使用新的新数组的数据刷新tableView。

这是我大多数功能的新代码(大部分)(有些链接到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!

由于对理解并不重要或敏感(例如,Youtube API密钥),因此未在此处粘贴某些部分。