Я искал по этой теме, но нашел очень мало деталей, которые были полезны. С этими деталями я попытался приготовить некоторый код следующим образом.
Примечание. Пожалуйста, сравните данные, представленные в этом посте, с другими постами, прежде чем пометить их как ДУБЛИРОВАННЫЕ, а не только по теме.
- (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];
}
Этот код собирает информацию об использовании Интернета устройством iPhone (а не только моим приложением).
Теперь, если я использую Интернет через WiFi или через 3G, я получаю данные (байты) только в ifi_obytes
(отправлено) и ifi_ibytes
(получено), но я думаю, что я должен получить использование WiFi в ifi_opackets
и ifi_ipackets
.
Также хотел бы добавить, что если я подключен к сети Wi-Fi, но не использую Интернет, я все равно получаю добавленную стоимость ifi_obytes
и ifi_ibytes
.
Может быть я не прав в реализации или понимании. Нужен кто-то, чтобы помочь мне.
Редактировать: вместо того, чтобы AF_LINK
я пытался AF_INET
( sockaddr_in
вместо sockaddr_dl
). Это вылетает приложение.
Важно понимать, что эти счетчики предоставляются с момента последней загрузки устройства.
Таким образом, чтобы эффективно использовать их, вы должны сопровождать каждый образец с временем работы устройства (вы можете использовать
mach_absolute_time()
- см. Это для получения дополнительной информации)Если у вас есть счетчики образцов + время работы, вы можете улучшить эвристику в отношении использования данных ...
источник
Чтобы добавить к принятому ответу, важно понимать, что объем данных, отображаемых интерфейсом, переполняется и перезапускается
0
после каждого4 GB
, особенно если вы используете этот код для вычисления разницы между двумя показаниями. Это потому, чтоifi_obytes
иifi_ibytes
есть,uint_32
и их максимальное значение4294967295
.Также я рекомендую использовать
unsigned int
s для переменных, содержащих отправленные и полученные данные. Обычныеint
s имеют половину максимального значения целого числа без знака, поэтому при добавленииifi_obytes
это может вызвать переполнение.источник
Свифт версия принятого ответа. Я также разбиваю код на более мелкие единицы.
источник
Я исправил приведенный выше исходный код в версии Swift3
источник
Новая версия, основанная на предыдущих версиях, но адаптированная для Swift4 и Xcode 9
источник
Извините за тот же ответ снова.
но я обнаружил, что UInt32 недостаточно, поэтому он падает, когда становится слишком большим.
Я только что изменил UInt32 на UInt64, и он работает нормально.
источник