SecAccessControlCreateWithFlags() in Swift
Asked Answered
U

1

6

I am trying to call a function in the Security.framework, from swift code. Forgetting about the "error out" (last) parameter for a second, if I call the function like this:

let accessControlRef = SecAccessControlCreateFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
            SecAccessControlCreateFlags.UserPresence,
            nil
        )

I ge tht efollowing error:

Cannot find an initializer for type 'SecAccessControlCreateFlags' that accepts an argument list of type '(CFAllocator!, CFStringRef, SecAccessControlCreateFlags, nil)'

...however, if I reformat my code to the following:

let allocator:CFAllocatorRef! = kCFAllocatorDefault

let protection:AnyObject!     = kSecAttrAccessibleWhenUnlockedThisDeviceOnly

let flags:SecAccessControlCreateFlags = SecAccessControlCreateFlags.UserPresence


let accessControlRef = SecAccessControlCreateWithFlags(
    allocator,
    protection,
    flags,
    nil
)

(specific types -e.g., CFAllocatorRef- taken from function prototype on Xcode's autocomplete)...it compiles with no problem. What's going on?

Next, the error parameter. What should I pass? Migrating my Objective-C code, I am tempted to pass the following variable (prepended with &, of course):

var accessControlError:CFErrorRef! = nil

...which gives the error:

Cannot invoke 'SecAccessControlCreateWithFlags' with an argument list of type '(CFAllocatorRef!, AnyObject!, SecAccessControlCreateFlags, inout CFErrorRef!)'

If, instead, I pass the following variable (again, prepended with the address-of operator):

var accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?>

(Same type as suggested by prototype autocomplete), I get:

Cannot invoke 'SecAccessControlCreateWithFlags' with an argument list of type '(CFAllocatorRef!, AnyObject!, SecAccessControlCreateFlags, inout UnsafeMutablePointer?>)'

...so, what gives?

EDIT: Forget about the error parameter. I seems I am taking the address twice (i.e., pointer to a pointer). Instead, I should do this:

var accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?> = nil
// ^ Already a 'pointer'

let allocator:CFAllocatorRef!         = kCFAllocatorDefault
let protection:AnyObject!             = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
let flags:SecAccessControlCreateFlags = SecAccessControlCreateFlags.UserPresence 

let accessControlRef = SecAccessControlCreateWithFlags(
        allocator,
        protection,
        flags,
        accessControlError // <- Notice the lack of '&'
)

Source: sample code within this answer.

Undersecretary answered 21/7, 2015 at 6:20 Comment(0)
U
11

(OK, so nobody has added any new insights in a while, so I will answer my own question with the contents of my last edit:)

ANSWER: Forget about the error parameter. I seems I am taking the address twice (i.e., pointer to a pointer). Instead, I should do this:

let accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?> = nil
// ^ Already a 'pointer'

let allocator:CFAllocator!         = kCFAllocatorDefault
let protection:AnyObject!             = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
let flags:SecAccessControlCreateFlags = SecAccessControlCreateFlags.userPresence 

let accessControlRef = SecAccessControlCreateWithFlags(
        allocator,
        protection,
        flags,
        accessControlError // <- Notice the lack of '&'
) 
Undersecretary answered 27/8, 2015 at 5:44 Comment(1)
FWIW, you can also use, "var error: Unmanaged<CFErrorRef>?" and pass a reference "&error" Ref: developer.apple.com/videos/play/wwdc2015/706Checkerbloom

© 2022 - 2024 — McMap. All rights reserved.