CFDictionary get Value for Key in Swift3
Don't use CFDictionary
in Swift. (It is possible, but not worth the effort, see below.)
CFDictionary
is toll-free
bridged withNSDictionary
, which in turn can be cast to a SwiftDictionary
.- The value of the
kDADiskDescriptionVolumeNetworkKey
key is aCFBoolean
which can be cast to a SwiftBool
.
Example:
if let session = DASessionCreate(kCFAllocatorDefault),
let mountedVolumes = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: []) {
for volume in mountedVolumes {
if let disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, volume as CFURL),
let diskinfo = DADiskCopyDescription(disk) as? [NSString: Any] {
if let networkValue = diskinfo[kDADiskDescriptionVolumeNetworkKey] as? Bool {
print(networkValue)
}
}
}
}
Just for the sake of completeness: This is the necessary pointer
juggling to call CFDictionaryGetValue
in Swift 3:
if let session = DASessionCreate(kCFAllocatorDefault),
let mountedVolumes = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: []) {
for volume in mountedVolumes {
if let disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, volume as CFURL),
let diskinfo = DADiskCopyDescription(disk) {
if let ptr = CFDictionaryGetValue(diskinfo, Unmanaged.passUnretained(kDADiskDescriptionVolumeNetworkKey).toOpaque()) {
let networkValue = Unmanaged<NSNumber>.fromOpaque(ptr).takeUnretainedValue()
print(networkValue.boolValue)
}
}
}
}
How to access CFDictionary in Swift 3?
If you don't have to deal with other Core Foundation functions expecting an CFDictionary
, you can simplify it by converting to Swift native Dictionary
:
if let dict = cfDict as? [String: AnyObject] {
print(dict["key"])
}
pass dictionary key to CFDictionaryGetValue
The easiest solution is to take advantage of the toll-free bridging
between CFDictionary
and NSDictionary
, and use the NSDictionary
accessor methods:
let ds = SCDynamicStoreCreate(nil, "setNet", nil, nil)!
if let list = SCDynamicStoreCopyProxies(ds) as NSDictionary? {
if let port = list[kSCPropNetProxiesHTTPPort as NSString] as? Int {
print("HTTPPort:", port)
}
}
But just for the sake of completeness: It can be done withCFDictionaryGetValue
:
if let list = SCDynamicStoreCopyProxies(ds) {
let key = kSCPropNetProxiesHTTPPort
let port = unsafeBitCast(CFDictionaryGetValue(list, unsafeAddressOf(key)), NSObject!.self)
if port != nil {
print("HTTPPort:", port)
}
}
Cannot access CFDictionary elements from Swift3
To fix your specific problem, replace metadata as? [String:Any]["{Exif}"]
with (metadata as! [String:Any])["{Exif}"]
The problem you are encountering is that metadata as? [String:Any]
is of type [String: Any]?
, since you are using the conditional cast as!
.
However, the idiomatic way to do this in Swift is to use guard-let
statements like so:
guard let metadata:CFDictionary = CGImageSourceCopyPropertiesAtIndex(source!,0,nil) else {
fatalError("Cannot get image properties!")
}
guard let dictionary = metadata as? [String: Any] else {
fatalError("Cannot convert metadata to dictionary!")
}
guard let exifData = dictionary["{Exif}"] as? [SomeCFType: Int] else { //I'm not sure what type PixelXDimension, PixelYDimension, and ColorSpace are
fatalError("Cannot get EXIF data!")
}
Swift 3 - Working with UnsafePointerCFDictionary?
Swift's CFDictionary
isn't itself a data structure; it's a pointer to a data structure, and it is equivalent to Objective-C's CFDictionaryRef
. In other words, it behaves like a Swift class
, not a struct
.
The value written into outDataPointer
is not a pointer to a CFDictionary
; it is a CFDictionary
. You're dereferencing it one too many times, causing the data stored in the dictionary to be treated as a pointer to a dictionary. On my system, the resulting memory address was 0x001dffffc892e2f1
, which Objective-C treats as a tagged pointer, resulting in the NSAtom
message.
To fix the problem, declare outDataPointer
as a CFDictionary?
instead of an UnsafePointer<CFDictionary>?
:
// Get metadata
var outDataPointer: CFDictionary? = nil
possibleError = AudioFileGetProperty(audiofile!, kAudioFilePropertyInfoDictionary, &outDataSize, &outDataPointer)
assert(possibleError == noErr)
let outData = outDataPointer! as NSDictionary
dump(outData)
Output:
▿ 1 key/value pair #0
▿ (2 elements)
- .0: approximate duration in seconds #1
- super: __NSCFString
- super: NSMutableString
- super: NSString
- super: NSObject
- .1: 187.387 #2
- super: NSString
- super: NSObject
Cast Swift Dictionary to CFDictionary
Yes you can do that. your solution will work and you can also do it like this.
var dictionary = [
key:value
] as CFDictionary
You can refer further from here
Swift 3 - Trying to cast a dictionary to CFDictionary
You can use below code to convert the dictionary to CFDictionary
as mention below:
let attrs = [kCVPixelBufferCGImageCompatibilityKey as String :kCFBooleanTrue,
kCVPixelBufferCGBitmapContextCompatibilityKey as String:kCFBooleanTrue] as
CFDictionary
Hope This will helps
Related Topics
Performing a Completion Handler Before App Launches
How to Get All Characters of the Font with Ctfontcopycharacterset() in Swift
Presenting a Uiviewcontroller from Skscene Shows Black Screen
Nsmanagedobject Subclasses Duplicate Declaration
Contextual Member Has No Associated Value in Swift 3
Var Declaration with Type VS Without
Runaction on Sknode Does Not Complete
Uicollectionviewcell Calling Functions Over and Over
Finding All Types That Conform to a Protocol
Why Is the Following Giving Me Zero
Aws Cognito/Getting User Information from the Sub
Swift Generic Func Cannot Convert Value of Type to Expected Argument Type
Firebase Datadescription Returns Empty Array
Toggle Selectedrange Attributes in Uitextview
Alamofire 4 Error Request 'Extra Argument in Call'
A Method Without Parameters Is Calling for an Argument