Swift 4 使用外部网络框架时将结果传输到主线程
Swift 4 Transfer results to main thread when using external networking framework
我想从服务器 api 获取数据。
问题是所有的网络框架都是异步的。
所以我遇到的问题是 return 变量 return 为空这是我的代码。
调用函数的视图控制器
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = "http://api.musixmatch.com/ws/1.1/track.lyrics.get?track_id=12693365&apikey=63ee7da5e2ee269067ecc42b25590922"
let musixrequest = MusicMatchRequest()
let endResults = musixrequest.gettingLyrics(url: url)
if !endResults.isEmpty{
print("The end results are \(endResults)")
}else{
print("No results found")
}
}
这是我的 class 我正在尝试获取数据的地方
public class MusicMatchRequest : NSObject{
public override init(){}
public func gettingLyrics(url : String) -> String {
var endResults = ""
DefaultProvider.request(Route(path:"\(url)")).responseJSON { (response:Response<Any>) in
switch response.result{
case .success(let json):
endResults = String(describing:json)
print(endResults)
case .failure(let error):
print("error: \(error)")
}
}
return endResults
}
}
当我从它正在工作的任务中打印 endRsults 时,它打印结果但 var endResults return 为空。
想法如何传输数据。
我尝试了两个框架
Alamofire
尼卡
在两个框架中它的行为相同。
Solution
我不完全知道引擎盖下发生了什么,但作为任何网络操作,这也必须是异步的(这意味着它需要一定的时间来获取数据)。
let endResults = musixrequest.gettingLyrics(url: url)
如果它在主线程上同步完成,它会阻塞它,因此用户无法与应用程序交互,这是非常糟糕的。鉴于它在您的代码中是异步的,您会立即在下一行中读取该值,此处:
if !endResults.isEmpty {
print("The end results are \(endResults)")
} else {
print("No results found")
}
网络操作不太可能在一行时间内完成,因此您不会在那里获得数据。
你应该做的是在这个方法中传递一个完成处理程序:
public func gettingLyrics(url : String) -> String
并像这样分派到主线程:
DispatchQueue.main.async {
// do you UI stuff here
}
将您的功能更改为:
public func gettingLyrics(url : String, completionHandler: (String) -> Void)
并在成功分支中调用完成处理程序:
completionHandler(String(describing:json))
我想从服务器 api 获取数据。 问题是所有的网络框架都是异步的。 所以我遇到的问题是 return 变量 return 为空这是我的代码。
调用函数的视图控制器
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = "http://api.musixmatch.com/ws/1.1/track.lyrics.get?track_id=12693365&apikey=63ee7da5e2ee269067ecc42b25590922"
let musixrequest = MusicMatchRequest()
let endResults = musixrequest.gettingLyrics(url: url)
if !endResults.isEmpty{
print("The end results are \(endResults)")
}else{
print("No results found")
}
}
这是我的 class 我正在尝试获取数据的地方
public class MusicMatchRequest : NSObject{
public override init(){}
public func gettingLyrics(url : String) -> String {
var endResults = ""
DefaultProvider.request(Route(path:"\(url)")).responseJSON { (response:Response<Any>) in
switch response.result{
case .success(let json):
endResults = String(describing:json)
print(endResults)
case .failure(let error):
print("error: \(error)")
}
}
return endResults
}
}
当我从它正在工作的任务中打印 endRsults 时,它打印结果但 var endResults return 为空。 想法如何传输数据。
我尝试了两个框架
Alamofire
尼卡
在两个框架中它的行为相同。
Solution 我不完全知道引擎盖下发生了什么,但作为任何网络操作,这也必须是异步的(这意味着它需要一定的时间来获取数据)。
let endResults = musixrequest.gettingLyrics(url: url)
如果它在主线程上同步完成,它会阻塞它,因此用户无法与应用程序交互,这是非常糟糕的。鉴于它在您的代码中是异步的,您会立即在下一行中读取该值,此处:
if !endResults.isEmpty {
print("The end results are \(endResults)")
} else {
print("No results found")
}
网络操作不太可能在一行时间内完成,因此您不会在那里获得数据。 你应该做的是在这个方法中传递一个完成处理程序:
public func gettingLyrics(url : String) -> String
并像这样分派到主线程:
DispatchQueue.main.async {
// do you UI stuff here
}
将您的功能更改为:
public func gettingLyrics(url : String, completionHandler: (String) -> Void)
并在成功分支中调用完成处理程序:
completionHandler(String(describing:json))