在iOS上检测WiFi启用/禁用的更好方法是什么?

在令人难以置信的牙齿咬牙切齿之后,我终于有了一种成功检测iOS上是否启用了WiFi的方法,而不管它是否已连接。 这种事情至少有几种用途,我认为这不违反Apple Law(tm)的精神或文字。

然而,它很丑陋,可能不会永远有效。 它目前适用于iOS 10.2.1,截至2017年1月31日。我将在下面给出我的答案,并希望有人可以改进它。 我已经大量研究了Reachability( 不符合要求 ),CaptiveNetwork,HotspotHelper,SCNetworkConfiguration,Xamarin的System.Net.NetworkInterface等等。 就我所知,这实际上是有效的。

解决方案的要点是,当getifaddrs()报告名称为“awdl0”的两个接口时,则启用WiFi。 只有一个,它被禁用了。

我认为pebble8888指向https://github.com/alirp88/SMTWiFiStatus这是Objective-C,缺乏评论使得很难理解发生了什么或作者的意图是什么。

这是我完整而完整的Xamarin / C#解决方案,对于任何其他主要语言用户来说应该是非常易读的:

using System; using System.Runtime.InteropServices; namespace Beacon.iOS { ///  /// code stolen from the Xamarin source code to work around goofy interactions between /// the good-god-why-would-it-work-that-way iOS and the entirely reasonable Xamarin /// (it doesn't report interfaces that are reported multiple times) ///  class XamHack { // // Types // internal struct ifaddrs { #pragma warning disable 0649 public IntPtr ifa_next; public string ifa_name; public uint ifa_flags; public IntPtr ifa_addr; public IntPtr ifa_netmask; public IntPtr ifa_dstaddr; public IntPtr ifa_data; #pragma warning restore } // // OS methods // [DllImport("libc")] protected static extern int getifaddrs(out IntPtr ifap); [DllImport("libc")] protected static extern void freeifaddrs(IntPtr ifap); // // Methods // ///  /// Our glorious hack. I apologize to the programming gods for my sins /// but this works (for now) and functionality trumps elegance. Even this. /// Reverse engineered from: https://github.com/alirp88/SMTWiFiStatus ///  public static bool IsWifiEnabled() { int count = 0; IntPtr ifap; // get the OS to put info about all the NICs into a linked list of buffers if (getifaddrs(out ifap) != 0) throw new SystemException("getifaddrs() failed"); try { // iterate throug those buffers IntPtr next = ifap; while (next != IntPtr.Zero) { // marshall the data into our struct ifaddrs addr = (ifaddrs)Marshal.PtrToStructure(next, typeof(ifaddrs)); // count the instances of the sacred interface name if ("awdl0" == addr.ifa_name) count++; // move on to the next interface next = addr.ifa_next; } } finally { // leaking memory is for jerks freeifaddrs(ifap); } // if there's two of the sacred interface, that means WiFi is enabled. Seriously. return (2 == count); } } // class } // namespace