ping 主机阵列并在 table 中显示结果
ping through host array and show results in table
我正在尝试 ping 一个包含不同主机的数组。在每个循环中,我都会根据 ping 是否成功(checkImg、errorImg)保存图像。之后,我想在 table.
中显示信息(主机名和 img)
以下代码确实可以正常工作,但不是 stable。有时我会收到以下警告:
Thread 1: Fatal error: Index out of range In line: imgServer.image =
UIImage(named: statusImagesMain[indexPath.row])
所以我想在执行 serverStatusTable.reloadData() 之前,不同主机的 ping 循环没有完成。
你知道我能做些什么来克服这个问题吗?
swift 4
import UIKit
class ServerVC: SimplePingDelegate, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var serverStatusTable: UITableView!
let imageError = UIImage(named: "error")
let imageCheck = UIImage(named: "check")
var pings = ["www.apple.com", "www.appleidontknowwhy.de", "www.apple.com", "www.apple.com"]
var hosts = [String]() // hostnames which get pinged
var componentTextArray = [String]() // project names
var statusImagesTemporary = [String]() // temporary store images
var statusImagesMain = [String]() // array filled with temporary stored images
var serverStatusMain = [String]() // server status string (connected, error)
var serverStatusTemporary = [String]() // temporary server status
override func viewDidLoad() {
super.viewDidLoad()
serverStatusTable.dataSource = self
serverStatusTable.delegate = self
statusImagesMain = ["error", "error", "error", "error"]
componentTextArray = ["Project 1", "Project 2", "Project 3", "Project 4"]
serverStatusMain = ["no data", "no data", "no data", "no data"]
hosts = pings
pingNext()
serverStatusTable.reloadData()
}
override func viewDidAppear(_ animated: Bool) {
// initial ping host process when loading the view
startHostRequest()
}
@IBAction func refreshBtnAction(_ sender: Any) {
// manual ping host process when clicking the button "refresh"
startHostRequest()
}
func startHostRequest () {
print("refresh server status")
pingNext()
// clear array before each host ping process in order for the array to keep only four items
statusImagesMain.removeAll()
serverStatusMain.removeAll()
for statusImageTemporary in statusImagesTemporary {
statusImagesMain.append(statusImageTemporary)
}
for i in serverStatusTemporary {
serverStatusMain.append(i)
}
serverStatusTable.reloadData()
}
func pingNext() {
guard pings.count > 0 else {
return
}
let ping = pings.removeFirst()
PlainPing.ping(ping, withTimeout: 1.0, completionBlock: { (timeElapsed:Double?, error:Error?) in
if let latency = timeElapsed {
print("\(ping) latency (ms): \(latency)")
// fill temporary arrays with img and serverStatus text for successful connection
self.statusImagesTemporary.append("check")
self.serverStatusTemporary.append("Running ")
}
if let error = error {
print("error: \(error.localizedDescription)")
// fill temporary arrays with img and serverStatus text for failed connection attempt
self.statusImagesTemporary.append("error")
self.serverStatusTemporary.append("Error ")
}
self.pingNext()
})
}
// fill table with host data
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return componentTextArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = serverStatusTable.dequeueReusableCell(withIdentifier: "serverStatusCell", for: indexPath)
let lblServerStatus : UILabel = cell.contentView.viewWithTag(8) as! UILabel
let imgServer : UIImageView = cell.contentView.viewWithTag(7) as! UIImageView
imgServer.image = UIImage(named: statusImagesMain[indexPath.row])
lblServerStatus.text = serverStatusMain[indexPath.row]
return cell
}
}
你的错误在于startHostRequest()
和tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
。
在startHostRequest()
中将statusImagesTemporary
复制到statusImagesMain
,statusImageTemporary
开始时为空,并以.reloadData()
结束。 tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
returns componentTextArray.count
总是 4。当这两个放在一起时,一旦 startHostRequest()
被调用, table 被重新加载,指示有 4 行,但是有0行数据需要填写
管理您的 UITableView
可以通过使用 ALTableViewHelper
[商业 - 在 here 上可用来简化
]. UITableView
的单元格为您维护 - 在您的情况下,与 statusImagesTemporary
:
的内容相匹配
class ServerVC: UIViewController, UITableViewDelegate {
@IBOutlet weak var serverStatusTable: UITableView!
@objc let imageError = UIImage(named: "error")
@objc let imageCheck = UIImage(named: "check")
var pings = ["www.apple.com", "www.appleidontknowwhy.de", "www.apple.com", "www.apple.com"]
var hosts = [String]() // hostnames which get pinged
@objc var componentTextArray = [String]() // project names
@objc var serverStatusMain = NSMutableArray() // not [String]() to allow changes to be observed
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// do not set dataSource, but instead:
serverStatusTable.setHelperString(
"section\n" +
" body\n" +
" serverStatusCell * serverStatusMain\n" +
" $.viewWithTag:(8).text <~ @[1] == 'error' ? 'Error ' : 'Running '\n" +
" $.viewWithTag:(7).image <~ @[1] == 'error' ? imageError : imageCheck \n" +
" $.viewWithTag:(2).text <~ componentTextArray[@[0]]\n" +
"", context:self)
// @ is the value from the array (serverStatusMain), and $ is the serverStatusCell for @
// The selector for UIView.viewWithTag() is 'viewWithTag:', which is why you see that in the helper string
// Short arrays were added below as the values in serverStatusMain. In each short array:
// [0] is the index into hosts[] and componentTextArray[]
// [1] is the result of the ping, ie "check" or "error"
// so @[0] is the index and @[1] is the result of the ping
serverStatusTable.delegate = self
componentTextArray = ["Project 1", "Project 2", "Project 3", "Project 4"]
hosts = pings
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
// initial ping host process when loading the view
startHostRequest()
}
@IBAction func refreshBtnAction(_ sender: Any) {
// manual ping host process when clicking the button "refresh"
startHostRequest()
}
func startHostRequest () {
// I thought you might need this here so that the 2nd and later ‘starts’ do the whole list
pings = hosts
// This will empty your UITableView
serverStatusMain.removeAllObjects()
print("refresh server status")
pingNext()
}
func pingNext() {
guard pings.count > 0 else {
return
}
let ping = pings.removeFirst()
PlainPing.ping(ping, withTimeout: 1.0, completionBlock: { [weak self](timeElapsed:Double?, error:Error?) in
if let me = self {
if let latency = timeElapsed {
print("\(ping) latency (ms): \(latency)")
me.serverStatusMain.add([me.serverStatusMain.count, "check"])
}
if let error = error {
print("error: \(error.localizedDescription)")
me.serverStatusMain.add([me.serverStatusMain.count, "error"])
}
me.pingNext()
}
})
}
}
您可以看到包含此代码的完整演示项目here。
我正在尝试 ping 一个包含不同主机的数组。在每个循环中,我都会根据 ping 是否成功(checkImg、errorImg)保存图像。之后,我想在 table.
中显示信息(主机名和 img)以下代码确实可以正常工作,但不是 stable。有时我会收到以下警告:
Thread 1: Fatal error: Index out of range In line: imgServer.image = UIImage(named: statusImagesMain[indexPath.row])
所以我想在执行 serverStatusTable.reloadData() 之前,不同主机的 ping 循环没有完成。
你知道我能做些什么来克服这个问题吗?
swift 4
import UIKit
class ServerVC: SimplePingDelegate, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var serverStatusTable: UITableView!
let imageError = UIImage(named: "error")
let imageCheck = UIImage(named: "check")
var pings = ["www.apple.com", "www.appleidontknowwhy.de", "www.apple.com", "www.apple.com"]
var hosts = [String]() // hostnames which get pinged
var componentTextArray = [String]() // project names
var statusImagesTemporary = [String]() // temporary store images
var statusImagesMain = [String]() // array filled with temporary stored images
var serverStatusMain = [String]() // server status string (connected, error)
var serverStatusTemporary = [String]() // temporary server status
override func viewDidLoad() {
super.viewDidLoad()
serverStatusTable.dataSource = self
serverStatusTable.delegate = self
statusImagesMain = ["error", "error", "error", "error"]
componentTextArray = ["Project 1", "Project 2", "Project 3", "Project 4"]
serverStatusMain = ["no data", "no data", "no data", "no data"]
hosts = pings
pingNext()
serverStatusTable.reloadData()
}
override func viewDidAppear(_ animated: Bool) {
// initial ping host process when loading the view
startHostRequest()
}
@IBAction func refreshBtnAction(_ sender: Any) {
// manual ping host process when clicking the button "refresh"
startHostRequest()
}
func startHostRequest () {
print("refresh server status")
pingNext()
// clear array before each host ping process in order for the array to keep only four items
statusImagesMain.removeAll()
serverStatusMain.removeAll()
for statusImageTemporary in statusImagesTemporary {
statusImagesMain.append(statusImageTemporary)
}
for i in serverStatusTemporary {
serverStatusMain.append(i)
}
serverStatusTable.reloadData()
}
func pingNext() {
guard pings.count > 0 else {
return
}
let ping = pings.removeFirst()
PlainPing.ping(ping, withTimeout: 1.0, completionBlock: { (timeElapsed:Double?, error:Error?) in
if let latency = timeElapsed {
print("\(ping) latency (ms): \(latency)")
// fill temporary arrays with img and serverStatus text for successful connection
self.statusImagesTemporary.append("check")
self.serverStatusTemporary.append("Running ")
}
if let error = error {
print("error: \(error.localizedDescription)")
// fill temporary arrays with img and serverStatus text for failed connection attempt
self.statusImagesTemporary.append("error")
self.serverStatusTemporary.append("Error ")
}
self.pingNext()
})
}
// fill table with host data
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return componentTextArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = serverStatusTable.dequeueReusableCell(withIdentifier: "serverStatusCell", for: indexPath)
let lblServerStatus : UILabel = cell.contentView.viewWithTag(8) as! UILabel
let imgServer : UIImageView = cell.contentView.viewWithTag(7) as! UIImageView
imgServer.image = UIImage(named: statusImagesMain[indexPath.row])
lblServerStatus.text = serverStatusMain[indexPath.row]
return cell
}
}
你的错误在于startHostRequest()
和tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
。
在startHostRequest()
中将statusImagesTemporary
复制到statusImagesMain
,statusImageTemporary
开始时为空,并以.reloadData()
结束。 tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
returns componentTextArray.count
总是 4。当这两个放在一起时,一旦 startHostRequest()
被调用, table 被重新加载,指示有 4 行,但是有0行数据需要填写
管理您的 UITableView
可以通过使用 ALTableViewHelper
[商业 - 在 UITableView
的单元格为您维护 - 在您的情况下,与 statusImagesTemporary
:
class ServerVC: UIViewController, UITableViewDelegate {
@IBOutlet weak var serverStatusTable: UITableView!
@objc let imageError = UIImage(named: "error")
@objc let imageCheck = UIImage(named: "check")
var pings = ["www.apple.com", "www.appleidontknowwhy.de", "www.apple.com", "www.apple.com"]
var hosts = [String]() // hostnames which get pinged
@objc var componentTextArray = [String]() // project names
@objc var serverStatusMain = NSMutableArray() // not [String]() to allow changes to be observed
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// do not set dataSource, but instead:
serverStatusTable.setHelperString(
"section\n" +
" body\n" +
" serverStatusCell * serverStatusMain\n" +
" $.viewWithTag:(8).text <~ @[1] == 'error' ? 'Error ' : 'Running '\n" +
" $.viewWithTag:(7).image <~ @[1] == 'error' ? imageError : imageCheck \n" +
" $.viewWithTag:(2).text <~ componentTextArray[@[0]]\n" +
"", context:self)
// @ is the value from the array (serverStatusMain), and $ is the serverStatusCell for @
// The selector for UIView.viewWithTag() is 'viewWithTag:', which is why you see that in the helper string
// Short arrays were added below as the values in serverStatusMain. In each short array:
// [0] is the index into hosts[] and componentTextArray[]
// [1] is the result of the ping, ie "check" or "error"
// so @[0] is the index and @[1] is the result of the ping
serverStatusTable.delegate = self
componentTextArray = ["Project 1", "Project 2", "Project 3", "Project 4"]
hosts = pings
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
// initial ping host process when loading the view
startHostRequest()
}
@IBAction func refreshBtnAction(_ sender: Any) {
// manual ping host process when clicking the button "refresh"
startHostRequest()
}
func startHostRequest () {
// I thought you might need this here so that the 2nd and later ‘starts’ do the whole list
pings = hosts
// This will empty your UITableView
serverStatusMain.removeAllObjects()
print("refresh server status")
pingNext()
}
func pingNext() {
guard pings.count > 0 else {
return
}
let ping = pings.removeFirst()
PlainPing.ping(ping, withTimeout: 1.0, completionBlock: { [weak self](timeElapsed:Double?, error:Error?) in
if let me = self {
if let latency = timeElapsed {
print("\(ping) latency (ms): \(latency)")
me.serverStatusMain.add([me.serverStatusMain.count, "check"])
}
if let error = error {
print("error: \(error.localizedDescription)")
me.serverStatusMain.add([me.serverStatusMain.count, "error"])
}
me.pingNext()
}
})
}
}
您可以看到包含此代码的完整演示项目here。