有人可以帮助我如何使用Swift从WWAN和WLAN获取数据使用情况吗?
我在Stack Overflow上发现如何在Objective-C中做到这一点,但解释会很好!
答案 0 :(得分:6)
let usage = getDataUsage()
// prints '3527660544 bytes of wifi'
print("\(usage.wifi.sent) bytes of wifi")
// prints '3.29 GB of wifi'
let usageString = ByteCountFormatter.string(fromByteCount: Int64(usage.wifi.sent), countStyle: .binary)
print("\(usageString) of wifi")
import Foundation
typealias DataUsage = (wifi: (sent: UInt32, received: UInt32), wwan: (sent: UInt32, received: UInt32))
func getDataUsage() -> DataUsage {
var interfaceAddresses: UnsafeMutablePointer<ifaddrs>?
let status = getifaddrs(&interfaceAddresses)
defer { freeifaddrs(interfaceAddresses) }
var returnData = DataUsage((0, 0), (0, 0))
guard status == 0, let addresses = interfaceAddresses else { return returnData }
for pointer in AddressSequence(interfaceAddresses: addresses) {
guard pointer.pointee.ifa_addr.pointee.sa_family == AF_LINK else { continue }
let networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
let (bytesIn, bytesOut) = (networkData.pointee.ifi_ibytes, networkData.pointee.ifi_obytes)
let name = String(cString: pointer.pointee.ifa_name)
if name.hasPrefix("en") {
returnData.wifi.sent += bytesOut
returnData.wifi.received += bytesIn
} else if name.hasPrefix("pdp_ip") {
returnData.wwan.sent += bytesOut
returnData.wwan.received += bytesIn
}
}
return returnData
}
class AddressSequence: Sequence {
init(interfaceAddresses: UnsafeMutablePointer<ifaddrs>) {
self.interfaceAddresses = interfaceAddresses
}
let interfaceAddresses: UnsafeMutablePointer<ifaddrs>
typealias Element = UnsafeMutablePointer<ifaddrs>
func makeIterator() -> AddressIterator {
return AddressIterator(currentPointer: interfaceAddresses)
}
}
class AddressIterator: IteratorProtocol {
init(currentPointer: UnsafeMutablePointer<ifaddrs>) {
self.currentPointer = currentPointer
}
var currentPointer: UnsafeMutablePointer<ifaddrs>?
public func next() -> UnsafeMutablePointer<ifaddrs>? {
currentPointer = currentPointer?.pointee.ifa_next ?? nil
return currentPointer
}
}
这是一种可能的实施方式。
首先,在您的Objective-C桥接标题中包含ifaddrs
:
#include <ifaddrs.h>
然后,试试这个功能:
func getDataUsage() -> (wifi : (sent : UInt32, received : UInt32), wwan : (sent : UInt32, received : UInt32)) {
var interfaceAddresses : UnsafeMutablePointer<ifaddrs> = nil
var networkData: UnsafeMutablePointer<if_data> = nil
var returnTuple : (wifi : (sent : UInt32, received : UInt32), wwan : (sent : UInt32, received : UInt32)) = ((0, 0), (0, 0))
if getifaddrs(&interfaceAddresses) == 0 {
for var pointer = interfaceAddresses; pointer != nil; pointer = pointer.memory.ifa_next {
let name : String! = String.fromCString(pointer.memory.ifa_name)
println(name);
let flags = Int32(pointer.memory.ifa_flags)
var addr = pointer.memory.ifa_addr.memory
if addr.sa_family == UInt8(AF_LINK) {
if name.hasPrefix("en") {
networkData = unsafeBitCast(pointer.memory.ifa_data, UnsafeMutablePointer<if_data>.self)
returnTuple.wifi.sent += networkData.memory.ifi_obytes
returnTuple.wifi.received += networkData.memory.ifi_ibytes
} else if name.hasPrefix("pdp_ip") {
networkData = unsafeBitCast(pointer.memory.ifa_data, UnsafeMutablePointer<if_data>.self)
returnTuple.wwan.sent += networkData.memory.ifi_obytes
returnTuple.wwan.received += networkData.memory.ifi_ibytes
}
}
}
freeifaddrs(interfaceAddresses)
}
return returnTuple
}
它返回嵌套的Swift元组,表示您请求的四个数据。这使得访问变得容易。例如:
let usage = getDataUsage()
let wifiDataSentString = "WiFi Data Sent: \(usage.wifi.sent)"
答案 1 :(得分:0)
更新了@Aaron Brager对Swift 4和Xcode 9的回答。
func getDataUsage() -> (wifi : (sent : UInt32, received : UInt32), wwan : (sent : UInt32, received : UInt32)) {
var interfaceAddresses : UnsafeMutablePointer<ifaddrs>? = nil
var networkData: UnsafeMutablePointer<if_data>? = nil
var pointer: UnsafeMutablePointer<ifaddrs>? = nil
var returnTuple : (wifi : (sent : UInt32, received : UInt32), wwan : (sent : UInt32, received : UInt32)) = ((0, 0), (0, 0))
if getifaddrs(&interfaceAddresses) == 0 {
pointer = interfaceAddresses
while pointer != nil {
let name : String = String.init(validatingUTF8: pointer!.pointee.ifa_name)!
let flags = UInt32((pointer?.pointee.ifa_flags)!)//Int32(pointer?.pointee.ifa_flags)
let addr = pointer?.pointee.ifa_addr.pointee
if addr?.sa_family == UInt8(AF_LINK) {
if name.hasPrefix("en") {
networkData = unsafeBitCast(pointer?.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
returnTuple.wifi.sent += (networkData?.pointee.ifi_obytes)!
returnTuple.wifi.received += (networkData?.pointee.ifi_ibytes)!
} else if name.hasPrefix("pdp_ip") {
networkData = unsafeBitCast(pointer?.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
returnTuple.wwan.sent += (networkData?.pointee.ifi_obytes)!
returnTuple.wwan.received += (networkData?.pointee.ifi_ibytes)!
}
}
pointer = pointer?.pointee.ifa_next
}
}
freeifaddrs(interfaceAddresses)
return returnTuple
}