iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
アプリ内課金のレシートを自分で解析する方法を調べていたら、公式ドキュメントにIO Kitを使ったMACアドレスを取り出すコードが説明されていたので、面白いので、Swiftで実装したコマンドラインのプログラムとして動かしてみた。
import IOKit
import Foundation
// Returns an object with a +1 retain count; the caller needs to release.
func io_service(named name: String, wantBuiltIn: Bool) -> io_service_t? {
let default_port = kIOMainPortDefault
var iterator = io_iterator_t()
defer {
if iterator != IO_OBJECT_NULL {
IOObjectRelease(iterator)
}
}
// CFMutableDictionaryRef IOBSDNameMatching(mach_port_t mainPort, uint32_t options, const char *bsdName);
guard let matchingDict = IOBSDNameMatching(default_port, 0, name),
// kern_return_t IOServiceGetMatchingServices(mach_port_t mainPort, CFDictionaryRef matching, io_iterator_t *existing);
IOServiceGetMatchingServices(default_port,
matchingDict as CFDictionary,
&iterator) == KERN_SUCCESS,
iterator != IO_OBJECT_NULL
else {
return nil
}
// io_object_t IOIteratorNext(io_iterator_t iterator);
var candidate = IOIteratorNext(iterator)
while candidate != IO_OBJECT_NULL {
// CFTypeRef IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options);
if let cftype = IORegistryEntryCreateCFProperty(candidate,
"IOBuiltin" as CFString,
kCFAllocatorDefault,
0) {
let isBuiltIn = cftype.takeRetainedValue() as! CFBoolean
if wantBuiltIn == CFBooleanGetValue(isBuiltIn) {
return candidate
}
}
IOObjectRelease(candidate)
candidate = IOIteratorNext(iterator)
}
return nil
}
func copy_mac_address() -> CFData? {
// Prefer built-in network interfaces.
// For example, an external Ethernet adaptor can displace
// the built-in Wi-Fi as en0.
guard let service = io_service(named: "en0", wantBuiltIn: true)
?? io_service(named: "en1", wantBuiltIn: true)
?? io_service(named: "en0", wantBuiltIn: false)
else { return nil }
defer { IOObjectRelease(service) }
// CFTypeRef IORegistryEntrySearchCFProperty(io_registry_entry_t entry, const io_name_t plane, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options);
if let cftype = IORegistryEntrySearchCFProperty(
service,
kIOServicePlane,
"IOMACAddress" as CFString,
kCFAllocatorDefault,
IOOptionBits(kIORegistryIterateRecursively | kIORegistryIterateParents)) {
return (cftype as! CFData)
}
return nil
}
func hexaDecimalString(_ cfData: CFData) -> String {
let data: Data = cfData as Data;
let value = data.map {
String(format: "%.2hhx", $0)
}
.joined(separator: ":")
return value
}
if let cfData = copy_mac_address() {
print("\(cfData)")
print("\(hexaDecimalString(cfData))")
}