2017-09-24 22 views
2

私は、SwiftでSystem Configurationフレームワークを使用して、macOSでネットワークインターフェイスの設定を読み込もうとしています。私は実際にCFDictionaryであるCFPropertyListを得ています。各辞書エントリにはCFArrayが含まれています。 CFShowと私は期待されたデータを得たことを確認することができました。私が実際に行うことができないのは、辞書の値にアクセスすることです。 CFGetTypeIdでは、私はCFArrayGetTypeID()によって返されたものと同じ値を得ていません。ここでCFPropertyListから値を読み取る

は、私は、プロパティリストからIPアドレスを取得しようとしたものです:次のように

import SystemConfiguration 

func readIP() { 

    let cfName = "Demo" as CFString 
    let dynamicStore = SCDynamicStoreCreate(nil, cfName, nil, nil) 

    let key = "State:/Network/Interface/en0/IPv4" as CFString 

    guard let plist: CFPropertyList = SCDynamicStoreCopyValue(dynamicStore, key) else {return} 

    print("CFShow(plist):") 
    CFShow(plist) 

    print("Key: \(key):") 
    print("Value: \(plist)") 

    let typeIdPList = CFGetTypeID(plist) 
    let typeIdDictionary = CFDictionaryGetTypeID() 

    print("typeIdPList: \(typeIdPList)") 
    print("typeIdDictionary: \(typeIdDictionary)") 

    guard typeIdPList == typeIdDictionary else {return} 

    let cfDict: CFDictionary = plist as! CFDictionary 

    let rawPointerToKeyAddresses = Unmanaged.passUnretained(kSCPropNetIPv4Addresses).toOpaque() 
    var rawPointerToValue: UnsafeRawPointer? 
    guard CFDictionaryGetValueIfPresent(cfDict, rawPointerToKeyAddresses, &rawPointerToValue) == true else {return} 

    let anyRef: CFTypeRef = rawPointerToValue as CFTypeRef 

    print("Value:") 
    CFShow(anyRef) 

    let typeIdValue = CFGetTypeID(anyRef) 
    let typeIdArray = CFArrayGetTypeID() 

    print("typeIdValue: \(typeIdValue)") 
    print("typeIdArray: \(typeIdArray)") 

    let cfArray: CFArray = anyRef as! CFArray 
    let typeId = CFGetTypeID(cfArray) 
    print("typeId: \(typeId)") 

    let desc = CFCopyDescription(anyRef) 
    let typeDesc = CFCopyTypeIDDescription(CFGetTypeID(anyRef)) 

    print("CFTypeRef description: \(desc!)") 
    print("CFTypeRef type description: \(typeDesc!)") 
} 

出力は次のようになります。

CFShow(plist): 
<CFBasicHash 0x610000069500 [0x7fffc4383da0]>{type = immutable dict, count = 3, entries => 
    0 : Addresses = <CFArray 0x610000069440 [0x7fffc4383da0]>{type = immutable, count = 1, values = (
    0 : <CFString 0x610000028980 [0x7fffc4383da0]>{contents = "192.168.139.24"} 
)} 
    1 : <CFString 0x610000044c20 [0x7fffc4383da0]>{contents = "BroadcastAddresses"} = <CFArray 0x610000069480 [0x7fffc4383da0]>{type = immutable, count = 1, values = (
    0 : <CFString 0x610000044c50 [0x7fffc4383da0]>{contents = "192.168.139.255"} 
)} 
    2 : <CFString 0x7fffc429d300 [0x7fffc4383da0]>{contents = "SubnetMasks"} = <CFArray 0x6100000694c0 [0x7fffc4383da0]>{type = immutable, count = 1, values = (
    0 : <CFString 0x6100000289a0 [0x7fffc4383da0]>{contents = "255.255.255.0"} 
)} 
} 
Key: State:/Network/Interface/en0/IPv4: 
Value: { 
    Addresses =  (
     "192.168.139.24" 
    ); 
    BroadcastAddresses =  (
     "192.168.139.255" 
    ); 
    SubnetMasks =  (
     "255.255.255.0" 
    ); 
} 
typeIdPList: 18 
typeIdDictionary: 18 
Value: 
0x0000610000069440 
typeIdValue: 1 
typeIdArray: 19 
typeId: 1 
CFTypeRef description: 0x0000610000069440 
CFTypeRef type description: CFType 

答えて

0

CFPropertyListはすでに添字をサポートしていますので、する必要はありませんCFDictionaryと生ポインタを使用すると、コードを簡略化することができます。

let cfName = "Demo" as CFString 
let dynamicStore = SCDynamicStoreCreate(nil, cfName, nil, nil) 
let key = "State:/Network/Interface/en0/IPv4" as CFString 

guard let plist = SCDynamicStoreCopyValue(dynamicStore, key) else {return} 
print(plist) 

if let addresses = plist[kSCPropNetIPv4Addresses] as? [String] { 
    print(addresses) 
} 
あなたは CFDictionary/ CFArray ベースのアプローチを機能させるためにどのように本当に興味がある場合

は、しかし:問題は、CFTypeRef(別名AnyObject)の中

let anyRef: CFTypeRef = rawPointerToValue as CFTypeRef 

ラップポインタ値。何をしたい はキャストへのポインタである:私は何を理解することである

let anyRef = Unmanaged<CFTypeRef>.fromOpaque(rawPointerToValue!).takeUnretainedValue() 
+0

let anyRef = unsafeBitCast(rawPointerToValue!, to: CFTypeRef.self) guard CFGetTypeID(anyRef) == CFArrayGetTypeID() else { return } let cfArray = anyRef as! CFArray // ... 

ポインタのキャストを行うことのもう一つの(等価)の方法があることCFDictionary'と 'NSDictionaryの'の間の架橋'はフリーダイヤルです。スウィフト辞書に橋渡しするのにはオーバーヘッドがあり、場合によっては問題になるかもしれません。説明されたユースケースではないかもしれません。なぜなら、ビュー要素のみが存在し、更新はまれですからです。 – Bokeh

+0

@Bokeh:CFPropertyListは既にサブスクリプトをサポートしているようですので、 'guard let plist = SCDynamicStoreCopyValue(dynamicStore、key)else {return}'は大文字と小文字を区別しません。 - そして、私は、スウィフトブリッジのコストが適切であるとは思っていません。 Apple Swiftブログのhttps://developer.apple.com/swift/blog/?id=37の例を比較してください。 –

+0

実際には、Core Foundationコレクションとrawポインタを使ってすべての面倒をする方法を理解したいと思います。私はそれらを何度も見つけ、問題が発生するたびに来ました。それ以外の場合は、パフォーマンス上の理由からCFインターフェイスを直接使用する必要があります。 – Bokeh

関連する問題