ios - 在 Swift 中将其分配给变量之前等待网络请求的结果

标签 ios swift networking grand-central-dispatch

我认为这个问题已经出现过很多次了,但我无法理解所有 GCD 和完成处理的内容。如果能快速修复并提供一些有用文章的链接,我们将不胜感激。

我有一个从网络请求获取和处理数据的函数:

  func getTracklist(album id: String) -> String {

        //create a GET request

        let task = URLSession.shared.dataTask(with: request) { (data, response, error) -> Void in
            guard let data = data else { return }
            let decoder = JSONDecoder()
            if let jsonTracks = try? decoder.decode(TrackRoot.self, from: data) {
                tracks = jsonTracks.items!
            }
            //append the tracklist string
            for track in tracks {
                combinedTracks += "\(track.id)%2C"
            }
        }
            task.resume()

        return String(combinedTracks.dropLast(3))

    }

返回值用于另一个函数:

formattedAlbum.trackList = self.getTracklist(album: album.id!)

正如您可能已经猜到的,第一个函数未能及时获取数据,并且为轨道列表分配了一个空字符串。

使用阿列克谢的答案:

for album in self.albums {
                let formattedAlbum = AlbumFormatted(context: self.persistenceManager.context)

                formattedAlbum.albumName = album.name
                self.getTracklist(album: album.id!) { (data) in
                    formattedAlbum.trackList = data
                }
                self.formattedAlbums.append(formattedAlbum)
                print(formattedAlbum)
            }
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(5)) {
                print(self.formattedAlbums[1])
            }
func getTracklist(album id: String, completion: @escaping (String?)->()) {
   //URLSession stuff

   let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
            guard let data = data else { return }
            let decoder = JSONDecoder()
            if let jsonTracks = try? decoder.decode(TrackRoot.self, from: data) {
                tracks = jsonTracks.items!
                for track in tracks {
                    combinedTracks += "\(track.id),"
                }
                completion(String(combinedTracks.dropLast()))
            }
        }
            task.resume()
    }

打印:

(entity: AlbumFormatted; id: 0x6000018fb400 <x-coredata:///AlbumFormatted/tFD0D9588-2820-451B-9A00-99175026ED043>; data: {
    albumName = "Everyday Life";
    trackList = "6Tb7Zfo4PcSiS4TqQ4NnTh,1e8D1BCD2afT56Km7UahpB,45PqOIkZ9PdCjsCJQYzx9G,1cXXhzPnbrXjNQYbLdUJdy,3pcPPhPAiurm2Ior11SHrz,7jib2tJjQ82kTIZZATMvAK,0ZlVUhjO8c0bOx1D2Btznf,0UvUivL70eDwhTWBd8S38I,6VzRvCbolqcUswaS";
})

最佳答案

我看到使用闭包的解决方案: 只需在 ViewController 中进行测试以供引用。

override func viewDidLoad() {
    super.viewDidLoad()
    getTracklist { data in
        print(data)
    }
}

func getTracklist(completion: @escaping (Data?)->()) {
    let request = URLRequest(url: URL(string: "https://jsonplaceholder.typicode.com/todos/1")!)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        // process errors here
        completion(data) // here you return your decoded data (I omit your json, as we don't have a model)
    }
    task.resume()
}

UPD 阅读您的评论后:

for album in self.albums { 
    let formattedAlbum = AlbumFormatted(context: self.persistenceManager.context) 
    formattedAlbum.albumName = album.name 
    self.getTracklist(album: album.id!) { data in 
        print(data) 
        formattedAlbum.trackList = data 
    }
    print(formattedAlbum.trackList) // will return you nil
    // here you will not have results in formattedAlbum.trackList, because getTracklist method processes the data asynchronously   
}

检查this , thatthis所以线程。

关于ios - 在 Swift 中将其分配给变量之前等待网络请求的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59054146/

相关文章:

java - MongoDB 复杂存储过程可以与 Java Web 服务一起使用吗

swift - 无法创建函数数组

c - "Replay"tcpdump 文件

ios - 如何从 Xcode 中的代码覆盖范围中排除 Pod

swift - 在 spritekit 中暂停游戏时显示菜单

ios - 本地通知发出声音但不显示(Swift)

networking - 嗅探检测

python - 如何计算子进程发出的每个 UDP 数据包?

Javascript 日期/时间不适用于带有 Chrome 的 iOS 设备

ios - .hidden = YES 工作但 .hidden = NO 不工作