Swift 按navigationItem按钮时,活动指示器未设置动画
我尝试在按下navigationItem按钮时触发活动指示器的动画。但我发现活动指示器没有旋转。我尝试将Swift 按navigationItem按钮时,活动指示器未设置动画,swift,uiactivityindicatorview,Swift,Uiactivityindicatorview,我尝试在按下navigationItem按钮时触发活动指示器的动画。但我发现活动指示器没有旋转。我尝试将scanerIndicator.startAnimating()放入主线程,但没有任何帮助 代码是从路由器打开的端口收集的,我想在按下navigationItem按钮时开始旋转,在返回openPorts时停止旋转。感谢您提供有关哪里出错的任何线索/提示 override func viewDidLoad() { super.viewDidLoad() .
scanerIndicator.startAnimating()
放入主线程,但没有任何帮助
代码是从路由器打开的端口收集的,我想在按下navigationItem按钮时开始旋转,在返回openPorts时停止旋转。感谢您提供有关哪里出错的任何线索/提示
override func viewDidLoad() {
super.viewDidLoad()
...
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Start", style: .plain, target: self, action: #selector(startScan))
...
}
@objc func startScan() {
scanerIndicator.startAnimating()
if let address = serverAddress.text, !address.isEmpty {
if let start = Int(startPort.text!) {
if let stop = Int(stopPort.text!) {
if start < stop {
openPorts = netUtility.scanPorts(address: address, start: start, stop: stop)
print("Open Open: \(openPorts)")
if !openPorts.isEmpty {
scanerIndicator.stopAnimating()
table.reloadData()
} else {
showErrorMessage(errorTitle: "Not at all", errorMessage: "No open ports were found")
}
} else {
showErrorMessage(errorTitle: "Range error", errorMessage: "Start port should be smaller than stop port")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
}
要理解您的代码在做什么有点困难,但我的猜测是,即使您使用队列进行端口扫描,因为您使用的是DispatchGroup,代码会一直阻塞,直到所有端口扫描完成 如果您有执行以下操作的同步代码:
scanerIndicator.startAnimating()
DispatchQueue.main.async {
//Do long-running task
scanerIndicator.stopAnimating()
}
这是因为在调用startAnimating()
之后,您将向主调度队列(在主线程上)添加一个异步调用,然后返回。应用程序的函数调用堆栈返回所有值,应用程序访问事件循环,活动指示器开始旋转。然后,系统接收添加到主队列中的异步任务,并开始运行该任务。最后,当长时间运行的任务完成时,关闭活动指示器(在内部调用的代码中)
async()
调用。最后,我终于让这段代码正常工作了,DispatchQueue
真的让我一整天都在焦头烂额
我的固定流程:
func abc() {
activityIndicator.startAnimating()
DispatchQueue.global(qos: .default).async {
// put your heavy code here
DispatchQueue.main.async {
// UI code must be on main thread
activityIndicator.stopAnimating()
}
}
}
我做什么
DispatchQueue.global(qos:.default).async
。我尝试先使用主线程,但失败了,而且长时间运行的代码应该在后台线程中。是global()
是后台线程吗?我稍后会深入了解:)@objc func startScan() {
scanerIndicator.startAnimating()
view.endEditing(true)
self.view.isUserInteractionEnabled = false
if let address = serverAddress.text, !address.isEmpty {
if let start = Int(startPort.text!) {
if let stop = Int(stopPort.text!) {
if start < stop {
netUtility.scanPorts(address: address, start: start, stop: stop) { [self] (availablePorts) in
openPorts = availablePorts
print("$Open ports: \(self.openPorts)")
if !openPorts.isEmpty {
DispatchQueue.main.async {
table.reloadData()
self.scanerIndicator.stopAnimating()
}
} else {
showErrorMessage(errorTitle: "Not at all", errorMessage: "No open ports were found")
}
}
} else {
showErrorMessage(errorTitle: "Range error", errorMessage: "Start port should be smaller than stop port")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
}
@objc func startScan(){
scanerIndicator.startAnimating()
view.endEditing(真)
self.view.isUserInteractionEnabled=false
如果let address=serverAddress.text,!address.isEmpty{
如果让start=Int(startPort.text!){
如果let stop=Int(stopPort.text!){
如果开始<停止{
扫描端口(地址:地址,开始:开始,停止:停止){[self](可用的报告)在
openPorts=可用的端口
打印(“$Open ports:\(self.openPorts)”)
如果!openPorts.isEmpty{
DispatchQueue.main.async{
表.重新加载数据()
self.scanerIndicator.stopAnimating()
}
}否则{
淋浴错误消息(错误标题:“根本没有”,错误消息:“未找到打开的端口”)
}
}
}否则{
淋浴错误信息(错误标题:“范围错误”,错误信息:“开始端口应小于停止端口”)
}
}否则{
淋浴信息(errorTitle:“空白字段”,errorMessage:“请填写所有必要的数据”)
}
}否则{
淋浴信息(errorTitle:“空白字段”,errorMessage:“请填写所有必要的数据”)
}
}否则{
淋浴信息(errorTitle:“空白字段”,errorMessage:“请填写所有必要的数据”)
}
}
谢谢,我尝试将长期运行代码放在主线程上,这一次,在返回长期运行代码后,指示器将设置动画。请看我的更新。我不明白你在说什么。您说“这一次,在返回长时间运行的代码之后,指示器将被设置为动画”。您是说,在进行更改之后,指示器将在扫描代码运行时旋转?“我的意思是,在返回长时间运行的代码后,指示器会旋转。好的,我已经检查了这一整天的问题,我还创建了一些简单的项目进行比较,并证明您的答案是正确的。因此,问题应该出现在我收集开放端口的代码中。我现在还在检查。谢谢邓肯,我现在已经修好了!
func abc() {
activityIndicator.startAnimating()
DispatchQueue.global(qos: .default).async {
// put your heavy code here
DispatchQueue.main.async {
// UI code must be on main thread
activityIndicator.stopAnimating()
}
}
}
// Scans ports from an address and a range given by the user
func scanPorts(address : String, start : Int, stop : Int, completion: @escaping ([Int]) -> ()) {
DispatchQueue.global(qos: .default).async {
for port in start...stop {
let client = TCPClient(address: address, port: Int32(port))
switch client.connect(timeout: 2) {
case .success:
self.openPorts.append(port)
print("HH: port: \(self.openPorts)")
case .failure(_):
print("port \(port) closed")
}
client.close()
}
completion(self.openPorts)
}
}
@objc func startScan() {
scanerIndicator.startAnimating()
view.endEditing(true)
self.view.isUserInteractionEnabled = false
if let address = serverAddress.text, !address.isEmpty {
if let start = Int(startPort.text!) {
if let stop = Int(stopPort.text!) {
if start < stop {
netUtility.scanPorts(address: address, start: start, stop: stop) { [self] (availablePorts) in
openPorts = availablePorts
print("$Open ports: \(self.openPorts)")
if !openPorts.isEmpty {
DispatchQueue.main.async {
table.reloadData()
self.scanerIndicator.stopAnimating()
}
} else {
showErrorMessage(errorTitle: "Not at all", errorMessage: "No open ports were found")
}
}
} else {
showErrorMessage(errorTitle: "Range error", errorMessage: "Start port should be smaller than stop port")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
} else {
showErrorMessage(errorTitle: "Empty fields", errorMessage: "Please fill all the necessary data")
}
}