Unsafemutablepointer<Cftyperef> in Swift 3

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



Leave a reply



Submit