UnsafeMutablePointer CFTypeRef in Swift 3
In your case, you do not need to use withMemoryRebound
or withUnsafeMutablePointer(to:)
.
Instead, you can just use
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
if status == noErr, let data = result as? Data {
//use data...
}
Generally, when you need to pass an UnsafeMutablePointer<T>
to a function, declare a variable of type T
and pass it as an inout argument &variable
. In your case, T
is CFTypeRef?
, and in Swift 3, CFTypeRef
is just a typealias of AnyObject
.
Even in Swift 2.2, you did not need to use withUnsafeMutablePointer
var result: AnyObject?
let status = SecItemCopyMatching(query, &result)
How to return a dictionary through a `UnsafeMutablePointer CFTypeRef? ?` parameter?
The working solution I found:
func SecItemCopyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus {
let item: [String: Any] = [
kSecAttrAccount as String: "username",
kSecValueData as String: "password".data(using: String.Encoding.utf8)!
]
result?.pointee = item as AnyObject
return copyMatchingStatus
}
They key information to understand: CFTypeRef
maps directly to AnyObject
(see Working with Core Foundation Types). Casting the dictionary to AnyObject
enables assignment as a pointee.
How to properly use CFStringGetCString in swift?
Why are you torturing yourself with CFStringGetCString
? If you have a CFString
in Swift, you can cast it to a String
and get a C string from that:
let cString: [Int8] = (cfString as String).cString(using: .utf8)!
Note also that the value of the kAXFocusedApplicationAttribute
is not a CFString
. It is an AXUIElement
.
Here's my playground test:
import Foundation
import CoreFoundation
let axSystem = AXUIElementCreateSystemWide()
var cfValue: CFTypeRef?
AXUIElementCopyAttributeValue(axSystem, kAXFocusedApplicationAttribute as CFString, &cfValue)
if let cfValue = cfValue, CFGetTypeID(cfValue) == AXUIElementGetTypeID() {
let axFocusedApplication = cfValue
print(axFocusedApplication)
}
The first time I executed this playground, I got a system dialog box telling me that I need to give Xcode permission to control my computer. I went to System Preferences > Security & Privacy > Privacy > Accessibility, found Xcode at the bottom of the list, and turned on its checkbox.
Here's the output of the playground:
<AXUIElement Application 0x7fb2d60001c0> {pid=30253}
I assume you're on macOS since the AXUI API is only available on macOS. If you just want the name of the front application as a string, you can do this:
if let frontAppName = NSWorkspace.shared.frontmostApplication?.localizedName {
print(frontAppName)
}
Accessing Objective-C Pointers in Swift
If you pass an UnsafeMutablePointer<Optional<AnyObject>>
as the last
argument to AXUIElementCopyAttributeValue()
then you must
initialize it by allocating (and ultimately releasing) memory:
var resultPtr: UnsafeMutablePointer<Optional<AnyObject>> = UnsafeMutablePointer.allocate(capacity: 1)
resultPtr.initialize(to: nil)
let result = AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, resultPtr)
// ...
resultPtr.deinitialize()
resultPtr.deallocate(capacity: 1)
It is easier
to pass the address of an Optional<AnyObject>
variable
with &
. Then conditionally
cast the received object to the expected type, in this case an
array of AXUIElement
:
var value: AnyObject?
let result = AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, &value)
if result == .success, let windowList = value as? [AXUIElement] {
// use `windowList`
}
and similarly:
if let window = windowList.first {
var value: AnyObject?
let result = AXUIElementCopyAttributeValue(window, kAXRoleAttribute as CFString, &value)
if result == .success, let role = value as? String {
// use `role` ...
}
}
One could define a generic utility function which encapsulates
all the casting:
func axUICopyAttributeValue<T>(of element: AXUIElement, attribute: String, as type: T.Type) -> T? {
var value: AnyObject?
let result = AXUIElementCopyAttributeValue(element, attribute as CFString, &value)
if result == .success, let typedValue = value as? T {
return typedValue
}
return nil
}
Example usage:
if let windowList = axUICopyAttributeValue(of: appRef, attribute: kAXWindowsAttribute, as:[AXUIElement].self) {
for window in windowList {
if let role = axUICopyAttributeValue(of: window, attribute: kAXRoleAttribute, as: String.self) {
// ...
}
}
}
Related Topics
Extending a Protocol Where Self: Generic Type in Swift (Requires Arguments in <...>)
Swift How to Convert Parse Createdat Time to Time Ago
Instance Member 'View' Cannot Be Used on Type 'Gamescene'
Swiftui How to Animate Each Character in Textfield
MAC App to Switch Between /Etc/Hosts Files, How to Allow Access
Swift: How to Fix Infinite Loop When Adding a Value to a Firebase Variable
Swift - Writing a Byte Stream to File
Sending Firebase Push Notifications to Logged-In Users Only
Button State Activates on Wrong Cells
Tvos Textfield Transparent Background
Attributed Text, Replace a Specific Font by Another Using Swift
In Swift, How to Wait Until a Server Response Is Received Before I Proceed
Unit Testing Wknavigationdelegate Functions
Firebase Access Keys in Queryorderby