【问题标题】:Tracking iPhone Data Usage [duplicate]跟踪 iPhone 数据使用 [重复]
【发布时间】:2015-04-06 00:03:09
【问题描述】:

有人可以帮我如何使用 Swift 从 WWAN 和 WLAN 获取数据使用情况吗?

我在 Stack Overflow 上找到了如何在 Objective-C 中做到这一点,但最好能解释一下!

Here is how to do that in Objective-C.

【问题讨论】:

  • 您是否尝试过自己重写该方法?这是一个有趣的练习。
  • 那么复杂吗?

标签: ios swift


【解决方案1】:

斯威夫特 4

示例用法

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)"

【讨论】:

  • 谢谢,我正在检查 :) 所以我是 IOS Dev 的新手,所以它对我有很大帮助!
  • 函数只返回0的数据使用量?:(
  • @BilalReffas 它对我有用。你是如何运行它的?
  • 当我按下按钮而不是运行函数时?喜欢你初始化
  • 桥接头及其正确的一切..:( wifi 和 wwan 使用返回 0 :(
【解决方案2】:

更新了 Swift 4 和 Xcode 9 的 @Aaron Brager 答案。

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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-30
    • 2014-01-27
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 2018-01-17
    相关资源
    最近更新 更多