Przeszukałem ten temat, ale znalazłem bardzo niewiele informacji, które były pomocne. Z tymi szczegółami próbowałem ugotować kod w następujący sposób.
Uwaga: przed oznaczeniem go jako DUPLIKAT porównaj szczegóły udostępnione w tym poście z innymi postami, a nie tylko temat.
- (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];
}
Ten kod zbiera informacje o korzystaniu z Internetu przez urządzenie iPhone (a nie tylko o mojej aplikacji).
Teraz, jeśli korzystam z Internetu przez Wi-Fi lub 3G, otrzymuję dane (bajty) tylko w ifi_obytes
(wysłane) i ifi_ibytes
(odebrane), ale myślę, że powinienem uzyskać korzystanie z WiFi w ifi_opackets
i ifi_ipackets
.
Chciałem też dodać, że jeśli jestem podłączony do sieci Wi-Fi, ale nie korzystam z Internetu, nadal otrzymuję wartość dodaną ifi_obytes
i ifi_ibytes
.
Może się mylę w implementacji lub rozumieniu Potrzebujesz kogoś, kto mi pomoże.
Edycja: Zamiast AF_LINK
próbowałem AF_INET
( sockaddr_in
zamiast sockaddr_dl
). To powoduje awarię aplikacji.
Ważne jest, aby zrozumieć, że liczniki te są dostarczane od ostatniego uruchomienia urządzenia.
Aby więc efektywnie je wykorzystać, do każdej próbki należy dołączyć czas pracy urządzenia (możesz użyć
mach_absolute_time()
- zobacz to po więcej informacji)Gdy masz już próbki liczników + czas pracy, możesz mieć lepszą heurystykę w zakresie wykorzystania danych ...
źródło
Aby dodać do zaakceptowanej odpowiedzi, ważne jest, aby zdać sobie sprawę, że ilość danych wyświetlanych przez interfejs przepełnia się i uruchamia się ponownie
0
po każdym4 GB
, zwłaszcza jeśli używasz tego kodu do obliczenia różnicy między dwoma odczytami. Dzieje się tak, ponieważifi_obytes
iifi_ibytes
są,uint_32
a ich maksymalna wartość to4294967295
.Polecam również używanie
unsigned int
s dla zmiennych zawierających wysłane i odebrane dane. Zwykłeint
s mają połowę maksymalnej wartości liczby całkowitej bez znaku, więc podczas dodawaniaifi_obytes
może spowodować przepełnienie.źródło
Szybka wersja zaakceptowanej odpowiedzi. Dzielę również kod na mniejsze jednostki.
źródło
Poprawiłem powyższy kod źródłowy do wersji Swift3
źródło
Nowa wersja oparta na poprzednich wersjach, ale dostosowana do Swift4 i Xcode 9
źródło
Przepraszam za tę samą odpowiedź ponownie.
ale stwierdziłem, że UInt32 nie wystarczy, więc ulega awarii, gdy staje się zbyt duży.
Właśnie zmieniłem UInt32 na UInt64 i działa dobrze.
źródło