我们班的任务是制作一个实现RESTful API调用的应用程序。我的应用程序有两个屏幕:
在这个项目的编写过程中,我们的任务是用“后台线程”指示代码段。我不确定“后台线程”在我的代码中的位置。
我找到了这个StackOverflow答案,它表示DispatchQueue中的代码。全局(qos:。后台)。异步{}在后台线程中运行,而代码在DispatchQueue.main中运行。异步{}在主线程中运行。然而,我只有DispatchQueue.main。异步{}和无调度队列。全局(qos:。后台)。异步{}。这是否意味着我没有背景线程?我现在必须实施吗?或者不是主线程中的所有内容都默认在后台线程中运行?
列出所有口袋妖怪类型的ViewController.swift代码如下:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
final let url = URL(string: "https://pokeapi.co/api/v2/type/")
private var results = [Movetype]()
@IBOutlet var tableView: UITableView!
var sequeIdentifiers = ["Normal", "Fighting", "Flying", "Poison", "Ground", "Rock", "Bug", "Ghost", "Steel", "Fire", "Water", "Grass", "Electric", "Psychic", "Ice", "Dragon", "Dark", "Fairy", "Unknown", "Shadow"]
override func viewDidLoad() {
super.viewDidLoad()
downloadJson()
// Do any additional setup after loading the view, typically from a nib.
}
func downloadJson() {
guard let downloadURL = url else { return }
URLSession.shared.dataTask(with: downloadURL) { data, urlResponse, error in
guard let data = data, error == nil, urlResponse != nil else {
print("something is wrong")
return
}
print("downloaded")
do
{
let decoder = JSONDecoder()
let downloaded_movetypes = try decoder.decode(Results.self, from: data)
self.results = downloaded_movetypes.results
DispatchQueue.main.async { // <- ********* MAIN THREAD *********
self.tableView.reloadData()
}
} catch {
print("something wrong after downloaded")
}
}.resume()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return results.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MovetypeCell") as? MovetypeCell else { return UITableViewCell() }
cell.Name_Label.text = results[indexPath.row].name.capitalized
let img_name = sequeIdentifiers[indexPath.row].lowercased() + ".png"
print(img_name)
cell.Img_View.image = UIImage(named: img_name)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//performSegue(withIdentifier: sequeIdentifiers[indexPath.row], sender: self)
let detailVc = self.storyboard?.instantiateViewController(withIdentifier: "Fighting") as! Fighting
detailVc.subType = sequeIdentifiers[indexPath.row].lowercased()
self.navigationController?.pushViewController(detailVc, animated: true)
}
}
哪一部分是背景线程?
我的应用程序第二个屏幕的代码Fighting.swift列出了所选类型的详细信息,如下所示:
var subType = ""
override func viewDidLoad() {
super.viewDidLoad()
self.title = subType.capitalized
let jsonUrlString = "https://pokeapi.co/api/v2/type/\(subType)/"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
// Get fighting JSON data
let fighting_json = try JSONDecoder().decode(fighting.self, from: data)
let detail_json = try JSONDecoder().decode(detailData.self, from: data)
print("Codementor == \(detail_json.damage_relations)")
print(fighting_json.damage_relations?.double_damage_from?.compactMap({ $0.name?.capitalized }) ?? "Bad data")
// Create Array: Double Damage From
let double_damage_from_fighting_array = fighting_json.damage_relations?.double_damage_from?.compactMap({ $0.name?.capitalized }) ?? ["Bad data"]
// Create Array: Double Damage To
let double_damage_to_fighting_array = fighting_json.damage_relations?.double_damage_to?.compactMap({ $0.name?.capitalized }) ?? ["Bad data"]
// Create Array: Half Damage From
let half_damage_from_fighting_array = fighting_json.damage_relations?.half_damage_from?.compactMap({ $0.name?.capitalized }) ?? ["Bad data"]
// Create Array: Half Damage To
let half_damage_to_fighting_array = fighting_json.damage_relations?.half_damage_to?.compactMap({ $0.name?.capitalized }) ?? ["Bad data"]
// Create Array: No Damage From
let no_damage_from_fighting_array = fighting_json.damage_relations?.no_damage_from?.compactMap({ $0.name?.capitalized }) ?? ["Bad data"]
// Create Array: No Damage To
let no_damage_to_fighting_array = fighting_json.damage_relations?.no_damage_to?.compactMap({ $0.name?.capitalized }) ?? ["Bad data"]
DispatchQueue.main.async { // <- ***** MAIN THREAD ******
// Print Label: Double Damage From
self.double_damage_from_fighting_Label.text = double_damage_from_fighting_array.joined(separator: ", ")
// Print Label: Double Damage To
self.double_damage_to_fighting_Label.text = double_damage_to_fighting_array.joined(separator: ", ")
// Print Label: Half Damage From
self.half_damage_from_fighting_Label.text = half_damage_from_fighting_array.joined(separator: ", ")
// Print Label: Half Damage To
self.half_damage_to_fighting_Label.text = half_damage_to_fighting_array.joined(separator: ", ")
// Print Label: No Damage From
self.no_damage_from_fighting_Label.text = no_damage_from_fighting_array.joined(separator: ", ")
// Print Label: No Damage To
self.no_damage_to_fighting_Label.text = no_damage_to_fighting_array.joined(separator: ", ")
}
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
}
该代码的哪一部分是后台线程?
我知道,在更改UI时,通常只需要调用主线程。这是否意味着在我的示例中,除了DispatchQueue.main中的代码外,do{}语句中的所有内容都在后台线程中。异步{}?
里面的所有请求和代码
URLSession.shared.dataTask(with: url) { (data, response, err) in
在后台线程、其他DispatchQueue.main中运行。async应仅为UI,如果设置正确,则使用此结构
DispatchQueue.global(qos: .background).async {
print("This is run on the background queue")
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
}
}
当你想运行一个长的本地/远程任务时,你希望它在后台线程(这里是全局队列)中,它将等同于你当前的代码,但它会自动切换到后台队列,而无需显式执行,这是URLSession.shared.dataTask的好处
考虑一下这段代码
let url = URL(string: image.url)
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
imageView.image = UIImage(data: data!)
将阻止主线程作为数据(内容在您放入的线程中运行,因此有2个选项
1-
DispatchQueue.global(qos: .background).async {
print("This is run on the background queue")
let url = URL(string: image.url)
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
imageView.image = UIImage(data: data!)
}
}
2-使用您当前的代码加载图像的数据
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
imageView.image = UIImage(data: data!)
}
}.resume()
因此,在使用任何方法之前,您应该事先知道它将在当前线程中运行的位置,如果主线程将被阻塞,直到请求完成,如果没有,则将其回调到DispatchQueue.main.async中以进行任何UI更新
每当您执行API调用时,如果有一个“完成处理程序”,那么它就是异步的。由于它是异步的,您不必费心把它放在线程中,框架会为您做这件事。
例如,如果您在视图上放置某种圆形进度条或任何动画,您将看到对URLSession.shared的调用。dataTask不会停止动画。
您仍然必须调用DispatchQueue.main.async
,因为当输入完成处理程序代码时,您位于dataTask
创建的线程上。
问题内容: 我正在Xcode 9 beta,iOS 11中使用Google Maps。 我收到如下错误输出到日志: 主线程检查器:在后台线程上调用的UI API:-[UIApplication applicationState] PID:4442,TID:837820,线程名称:com.google.Maps.LabelingBehavior,队列名称:com.apple.root.default
问题内容: 我最近了解到,只需添加批注,就可以轻松地使任何会话bean方法异步。 例如 我知道Java EE 7添加了Concurrency Utilities ,但是在Java EE 6中,方法的线程池配置在哪里?有没有办法设置超时时间?是固定线程池吗?一个缓存的?优先级是什么?是否可以在容器中的某个位置进行配置? 问题答案: 我认为可以通过从@Timeout注释的方法调用Future.canc
问题内容: 我对Tomcat不太熟悉,在我看来,它基本上是抽象为cgi服务器,可以在两次调用之间保存JVM -尽管我知道它可以做得多。 我正在寻找一种在Tomcat服务器启动时启动 后台 线程的方法,该方法会定期更新服务器上下文(在我的特殊情况下,这是一个侦听其他服务的心跳并更新可用性信息的线程,但是可以想象得到有多种用途)。 有标准的方法吗?上下文的启动和更新/查询? 指向相关文档和/或代码示例
本文向大家介绍C#中前台线程和后台线程的区别与联系,包括了C#中前台线程和后台线程的区别与联系的使用技巧和注意事项,需要的朋友参考一下 前台线程和后台线程的区别和联系: 1、后台线程不会阻止进程的终止。属于某个进程的所有前台线程都终止后,该进程就会被终止。所有剩余的后台线程都会停止且不会完成。 2、可以在任何时候将前台线程修改为后台线程,方式是设置Thread.IsBackground 属性。 3
我想让一些代码在后台持续运行。我不想在服务中这样做。还有其他可能的方法吗? 我曾尝试在我的活动中调用线程类,但我的活动在后台保留了一段时间,然后就停止了。线程类也停止工作。