iPhone Data Usage Tracking/Monitoring

The thing is that pdp_ip0 is one of interfaces, all pdpXXX are WWAN interfaces dedicated to different functions, voicemail, general networking interface.

I read in Apple forum that : The OS does not keep network statistics on a process-by-process basis. As such, there's no exact solution to this problem. You can, however, get network statistics for each network interface.

In general en0 is your Wi-Fi interface and pdp_ip0 is your WWAN interface.

There is no good way to get information wifi/cellular network data since, particular date-time!

Data statistic (ifa_data->ifi_obytes and ifa_data->ifi_ibytes) are stored from previous device reboot.

I don't know why, but ifi_opackets and ifi_ipackets are shown just for lo0 (I think its main interface ).

Yes. Then device is connected via WiFi and doesn't use internet if_iobytes values still come because this method provides network bytes exchanges and not just internet.

#include <net/if.h>
#include <ifaddrs.h>

static NSString *const DataCounterKeyWWANSent = @"WWANSent";
static NSString *const DataCounterKeyWWANReceived = @"WWANReceived";
static NSString *const DataCounterKeyWiFiSent = @"WiFiSent";
static NSString *const DataCounterKeyWiFiReceived = @"WiFiReceived";

NSDictionary *DataCounters()
{
    struct ifaddrs *addrs;
    const struct ifaddrs *cursor;

    u_int32_t WiFiSent = 0;
    u_int32_t WiFiReceived = 0;
    u_int32_t WWANSent = 0;
    u_int32_t WWANReceived = 0;

    if (getifaddrs(&addrs) == 0)
    {
        cursor = addrs;
        while (cursor != NULL)
        {
            if (cursor->ifa_addr->sa_family == AF_LINK)
            {
#ifdef DEBUG
                const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                if (ifa_data != NULL)
                {
                    NSLog(@"Interface name %s: sent %tu received %tu",cursor->ifa_name,ifa_data->ifi_obytes,ifa_data->ifi_ibytes);
                }
#endif

                // name of interfaces:
                // en0 is WiFi
                // pdp_ip0 is WWAN
                NSString *name = @(cursor->ifa_name);
                if ([name hasPrefix:@"en"])
                {
                    const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                    if (ifa_data != NULL)
                    {
                        WiFiSent += ifa_data->ifi_obytes;
                        WiFiReceived += ifa_data->ifi_ibytes;
                    }
                }

                if ([name hasPrefix:@"pdp_ip"])
                {
                    const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                    if (ifa_data != NULL)
                    {
                        WWANSent += ifa_data->ifi_obytes;
                        WWANReceived += ifa_data->ifi_ibytes;
                    }
                }
            }

            cursor = cursor->ifa_next;
        }

        freeifaddrs(addrs);
    }

    return @{DataCounterKeyWiFiSent : @(WiFiSent),
             DataCounterKeyWiFiReceived : @(WiFiReceived),
             DataCounterKeyWWANSent : @(WWANSent),
             DataCounterKeyWWANReceived : @(WWANReceived)};
}

Improved copy/paste support !


It's important to understand that these counters are provided since the device's last boot.

So, to make effective use of them, you should accompany every sample with the device's uptime (you can use mach_absolute_time() - see this for more information)

Once you have counters samples + uptime you can have better heuristics as to data use...


To add to the accepted answer, its important to realize that the amount of data displayed by the interface overflows and restarts at 0 after every 4 GB, especially if you are using this code to calculate the difference between two readings. This is because ifi_obytes and ifi_ibytes are uint_32 and their max value is 4294967295.

Also, I recommend using unsigned ints for the variables containing the data sent and received. Regular ints have half the max value of an unsigned integer, so when adding ifi_obytes, it may cause an overflow.

unsigned int sent = 0;
sent += networkStatisc->ifi_obytes;