Saya telah mencari topik ini tetapi menemukan sangat sedikit detail yang berguna. Dengan detail tersebut saya sudah mencoba memasak beberapa kode sebagai berikut.
Catatan: Silakan bandingkan detail yang dibagikan dalam posting ini dengan posting lain sebelum menandai ini sebagai DUPLICATE, dan bukan hanya dengan subjeknya.
- (NSArray *)getDataCountersForType:(int)type {
BOOL success;
struct ifaddrs *addrs = nil;
const struct ifaddrs *cursor = nil;
const struct sockaddr_dl *dlAddr = nil;
const struct if_data *networkStatisc = nil;
int dataSent = 0;
int dataReceived = 0;
success = getifaddrs(&addrs) == 0;
if (success) {
cursor = addrs;
while (cursor != NULL) {
if (cursor->ifa_addr->sa_family == AF_LINK) {
dlAddr = (const struct sockaddr_dl *) cursor->ifa_addr;
networkStatisc = (const struct if_data *) cursor->ifa_data;
if (type == WiFi) {
dataSent += networkStatisc->ifi_opackets;
dataReceived += networkStatisc->ifi_ipackets;
}
else if (type == WWAN) {
dataSent += networkStatisc->ifi_obytes;
dataReceived += networkStatisc->ifi_ibytes;
}
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
return [NSArray arrayWithObjects:[NSNumber numberWithInt:dataSent], [NSNumber numberWithInt:dataReceived], nil];
}
Kode ini mengumpulkan informasi penggunaan internet perangkat iPhone (dan bukan aplikasi saya sendiri).
Sekarang, jika saya menggunakan internet melalui WiFi atau melalui 3G, saya mendapatkan data (byte) hanya dalam ifi_obytes
(dikirim) dan ifi_ibytes
(diterima) tetapi saya pikir saya harus mendapatkan penggunaan WiFi di ifi_opackets
dan ifi_ipackets
.
Juga ingin menambahkan bahwa jika saya terhubung ke jaringan WiFi, tetapi tidak menggunakan internet, saya masih mendapatkan nilai tambah ke ifi_obytes
dan ifi_ibytes
.
Mungkin saya salah dalam implementasi atau pemahamannya. Butuh seseorang untuk membantuku.
Sunting: Alih-alih AF_LINK
saya mencoba AF_INET
( sockaddr_in
bukan sockaddr_dl
). Ini merusak aplikasi.
Penting untuk dipahami bahwa penghitung ini disediakan sejak boot terakhir perangkat.
Jadi, untuk memanfaatkannya secara efektif, Anda harus menemani setiap sampel dengan waktu aktif perangkat (Anda dapat menggunakan
mach_absolute_time()
- lihat ini untuk informasi lebih lanjut)Setelah Anda memiliki sampel penghitung + waktu aktif, Anda dapat memiliki heuristik yang lebih baik untuk penggunaan data ...
sumber
Untuk menambah jawaban yang diterima, penting untuk disadari bahwa jumlah data yang ditampilkan oleh antarmuka melimpah dan dimulai ulang
0
setelah setiap4 GB
, terutama jika Anda menggunakan kode ini untuk menghitung perbedaan antara dua bacaan. Ini karenaifi_obytes
danifi_ibytes
sedanguint_32
dan nilai maksimalnya adalah4294967295
.Juga, saya merekomendasikan menggunakan
unsigned int
s untuk variabel yang berisi data yang dikirim dan diterima. Regularint
s memiliki setengah dari nilai maksimal dari unsigned integer, jadi saat ditambahkanifi_obytes
, ini dapat menyebabkan overflow.unsigned int sent = 0; sent += networkStatisc->ifi_obytes;
sumber
Versi cepat dari jawaban yang diterima. Saya juga memecah kode menjadi unit yang lebih kecil.
struct DataUsageInfo { var wifiReceived: UInt32 = 0 var wifiSent: UInt32 = 0 var wirelessWanDataReceived: UInt32 = 0 var wirelessWanDataSent: UInt32 = 0 mutating func updateInfoByAdding(info: DataUsageInfo) { wifiSent += info.wifiSent wifiReceived += info.wifiReceived wirelessWanDataSent += info.wirelessWanDataSent wirelessWanDataReceived += info.wirelessWanDataReceived } } class DataUsage { private static let wwanInterfacePrefix = "pdp_ip" private static let wifiInterfacePrefix = "en" class func getDataUsage() -> DataUsageInfo { var interfaceAddresses: UnsafeMutablePointer<ifaddrs> = nil var dataUsageInfo = DataUsageInfo() guard getifaddrs(&interfaceAddresses) == 0 else { return dataUsageInfo } var pointer = interfaceAddresses while pointer != nil { guard let info = getDataUsageInfo(from: pointer) else { pointer = pointer.memory.ifa_next continue } dataUsageInfo.updateInfoByAdding(info) pointer = pointer.memory.ifa_next } freeifaddrs(interfaceAddresses) return dataUsageInfo } private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? { let pointer = infoPointer let name: String! = String.fromCString(infoPointer.memory.ifa_name) let addr = pointer.memory.ifa_addr.memory guard addr.sa_family == UInt8(AF_LINK) else { return nil } return dataUsageInfo(from: pointer, name: name) } private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo { var networkData: UnsafeMutablePointer<if_data> = nil var dataUsageInfo = DataUsageInfo() if name.hasPrefix(wifiInterfacePrefix) { networkData = unsafeBitCast(pointer.memory.ifa_data, UnsafeMutablePointer<if_data>.self) dataUsageInfo.wifiSent += networkData.memory.ifi_obytes dataUsageInfo.wifiReceived += networkData.memory.ifi_ibytes } else if name.hasPrefix(wwanInterfacePrefix) { networkData = unsafeBitCast(pointer.memory.ifa_data, UnsafeMutablePointer<if_data>.self) dataUsageInfo.wirelessWanDataSent += networkData.memory.ifi_obytes dataUsageInfo.wirelessWanDataReceived += networkData.memory.ifi_ibytes } return dataUsageInfo } }
sumber
Saya memperbaiki kode sumber di atas ke versi Swift3
struct DataUsageInfo { var wifiReceived: UInt32 = 0 var wifiSent: UInt32 = 0 var wirelessWanDataReceived: UInt32 = 0 var wirelessWanDataSent: UInt32 = 0 mutating func updateInfoByAdding(_ info: DataUsageInfo) { wifiSent += info.wifiSent wifiReceived += info.wifiReceived wirelessWanDataSent += info.wirelessWanDataSent wirelessWanDataReceived += info.wirelessWanDataReceived } } class DataUsage { private static let wwanInterfacePrefix = "pdp_ip" private static let wifiInterfacePrefix = "en" class func getDataUsage() -> DataUsageInfo { var ifaddr: UnsafeMutablePointer<ifaddrs>? var dataUsageInfo = DataUsageInfo() guard getifaddrs(&ifaddr) == 0 else { return dataUsageInfo } while let addr = ifaddr { guard let info = getDataUsageInfo(from: addr) else { ifaddr = addr.pointee.ifa_next continue } dataUsageInfo.updateInfoByAdding(info) ifaddr = addr.pointee.ifa_next } freeifaddrs(ifaddr) return dataUsageInfo } private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? { let pointer = infoPointer let name: String! = String(cString: pointer.pointee.ifa_name) let addr = pointer.pointee.ifa_addr.pointee guard addr.sa_family == UInt8(AF_LINK) else { return nil } return dataUsageInfo(from: pointer, name: name) } private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo { var networkData: UnsafeMutablePointer<if_data>? var dataUsageInfo = DataUsageInfo() if name.hasPrefix(wifiInterfacePrefix) { networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self) if let data = networkData { dataUsageInfo.wifiSent += data.pointee.ifi_obytes dataUsageInfo.wifiReceived += data.pointee.ifi_ibytes } } else if name.hasPrefix(wwanInterfacePrefix) { networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self) if let data = networkData { dataUsageInfo.wirelessWanDataSent += data.pointee.ifi_obytes dataUsageInfo.wirelessWanDataReceived += data.pointee.ifi_ibytes } } return dataUsageInfo } }
sumber
Versi baru tentang berdasarkan versi sebelumnya, tetapi diadaptasi untuk Swift4 dan Xcode 9
struct DataUsageInfo { var wifiReceived: UInt32 = 0 var wifiSent: UInt32 = 0 var wirelessWanDataReceived: UInt32 = 0 var wirelessWanDataSent: UInt32 = 0 mutating func updateInfoByAdding(info: DataUsageInfo) { wifiSent += info.wifiSent wifiReceived += info.wifiReceived wirelessWanDataSent += info.wirelessWanDataSent wirelessWanDataReceived += info.wirelessWanDataReceived } } class DataUsage { private static let wwanInterfacePrefix = "pdp_ip" private static let wifiInterfacePrefix = "en" class func getDataUsage() -> DataUsageInfo { var interfaceAddresses: UnsafeMutablePointer<ifaddrs>? = nil var dataUsageInfo = DataUsageInfo() guard getifaddrs(&interfaceAddresses) == 0 else { return dataUsageInfo } var pointer = interfaceAddresses while pointer != nil { guard let info = getDataUsageInfo(from: pointer!) else { pointer = pointer!.pointee.ifa_next continue } dataUsageInfo.updateInfoByAdding(info: info) pointer = pointer!.pointee.ifa_next } freeifaddrs(interfaceAddresses) return dataUsageInfo } private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? { let pointer = infoPointer let name: String! = String(cString: infoPointer.pointee.ifa_name) let addr = pointer.pointee.ifa_addr.pointee guard addr.sa_family == UInt8(AF_LINK) else { return nil } return dataUsageInfo(from: pointer, name: name) } private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo { var networkData: UnsafeMutablePointer<if_data>? = nil var dataUsageInfo = DataUsageInfo() if name.hasPrefix(wifiInterfacePrefix) { networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self) dataUsageInfo.wifiSent += networkData?.pointee.ifi_obytes ?? 0 dataUsageInfo.wifiReceived += networkData?.pointee.ifi_ibytes ?? 0 } else if name.hasPrefix(wwanInterfacePrefix) { networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self) dataUsageInfo.wirelessWanDataSent += networkData?.pointee.ifi_obytes ?? 0 dataUsageInfo.wirelessWanDataReceived += networkData?.pointee.ifi_ibytes ?? 0 } return dataUsageInfo } }
sumber
Maaf untuk jawaban yang sama lagi.
tetapi saya menemukan bahwa UInt32 tidak cukup, jadi akan macet ketika menjadi terlalu besar.
Saya baru saja mengubah UInt32 menjadi UInt64 dan berfungsi dengan baik.
struct DataUsageInfo { var wifiReceived: UInt64 = 0 var wifiSent: UInt64 = 0 var wirelessWanDataReceived: UInt64 = 0 var wirelessWanDataSent: UInt64 = 0 mutating func updateInfoByAdding(info: DataUsageInfo) { wifiSent += info.wifiSent wifiReceived += info.wifiReceived wirelessWanDataSent += info.wirelessWanDataSent wirelessWanDataReceived += info.wirelessWanDataReceived } } class DataUsage { private static let wwanInterfacePrefix = "pdp_ip" private static let wifiInterfacePrefix = "en" class func getDataUsage() -> DataUsageInfo { var interfaceAddresses: UnsafeMutablePointer<ifaddrs>? = nil var dataUsageInfo = DataUsageInfo() guard getifaddrs(&interfaceAddresses) == 0 else { return dataUsageInfo } var pointer = interfaceAddresses while pointer != nil { guard let info = getDataUsageInfo(from: pointer!) else { pointer = pointer!.pointee.ifa_next continue } dataUsageInfo.updateInfoByAdding(info: info) pointer = pointer!.pointee.ifa_next } freeifaddrs(interfaceAddresses) return dataUsageInfo } private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? { let pointer = infoPointer let name: String! = String(cString: infoPointer.pointee.ifa_name) let addr = pointer.pointee.ifa_addr.pointee guard addr.sa_family == UInt8(AF_LINK) else { return nil } return dataUsageInfo(from: pointer, name: name) } private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo { var networkData: UnsafeMutablePointer<if_data>? = nil var dataUsageInfo = DataUsageInfo() if name.hasPrefix(wifiInterfacePrefix) { networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self) dataUsageInfo.wifiSent += UInt64(networkData?.pointee.ifi_obytes ?? 0) dataUsageInfo.wifiReceived += UInt64(networkData?.pointee.ifi_ibytes ?? 0) } else if name.hasPrefix(wwanInterfacePrefix) { networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self) dataUsageInfo.wirelessWanDataSent += UInt64(networkData?.pointee.ifi_obytes ?? 0) dataUsageInfo.wirelessWanDataReceived += UInt64(networkData?.pointee.ifi_ibytes ?? 0) } return dataUsageInfo } }
sumber