AuthorizationCreate in Swift (Xcode 6) - macos

I've been looking for some help in creating authorization for my app to have it run a few shell scripts as root. I've looked through the Apple documentation (which is of course written in OBJ-C and quite vague) and I'm trying to use the code examples in Swift.
Immediately I'm running in an error with the AuthorizationCreate function:
var authRef: AuthorizationRef
let osStatus = AuthorizationCreate(nil, nil, kAuthorizationFlagDefaults, &authRef)
'Int' is not convertible to 'AuthorizationFlags'
I'm just trying to follow along with the code snippets in the docs from: https://developer.apple.com/library/mac/documentation/Security/Conceptual/authorization_concepts/03authtasks/authtasks.html#//apple_ref/doc/uid/TP30000995-CH206-TP9
And I found the constant for kAuthorizationFlagDefaults from here: https://developer.apple.com/library/mac/documentation/Security/Reference/authorization_ref/#//apple_ref/doc/constant_group/Authorization_Options
I'm running in 10.10.1 if that matters.
I've seen the solution for using AppleScript, but I really want to avoid this is possible.

kAuthorizationFlagDefaults is an Int and has to be converted to
AuthorizationFlags (which is a type alias for UInt32). Also authRef has to be initialized:
var authRef: AuthorizationRef = nil
let authFlags = AuthorizationFlags(kAuthorizationFlagDefaults)
let osStatus = AuthorizationCreate(nil, nil, authFlags, &authRef)
Extended example (untested!):
var myItems = [
AuthorizationItem(name: "com.myOrganization.myProduct.myRight1",
valueLength: 0, value: nil, flags: 0),
AuthorizationItem(name: "com.myOrganization.myProduct.myRight2",
valueLength: 0, value: nil, flags: 0)
]
var myRights = AuthorizationRights(count: UInt32(myItems.count), items: &myItems)
let myFlags = AuthorizationFlags(kAuthorizationFlagDefaults |
kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagExtendRights)
var authRef: AuthorizationRef = nil
let authFlags = AuthorizationFlags(kAuthorizationFlagDefaults)
let osStatus = AuthorizationCreate(&myRights, nil, authFlags, &authRef)
Edit: Swift 3
var myItems = [
AuthorizationItem(name: "com.myOrganization.myProduct.myRight1",
valueLength: 0, value: nil, flags: 0),
AuthorizationItem(name: "com.myOrganization.myProduct.myRight2",
valueLength: 0, value: nil, flags: 0)
]
var myRights = AuthorizationRights(count: UInt32(myItems.count), items: &myItems)
let myFlags : AuthorizationFlags = [.interactionAllowed, .extendRights]
var authRef: AuthorizationRef?
let osStatus = AuthorizationCreate(&myRights, nil, myFlags, &authRef)

Related

EXEC_BAD_INSTRUCTION (code=1, address=0xe) with MusicSequenceBarBeatTimeToBeats in Swift 2

I have problem when using Apples MusicSequence C API in Swift 2. I can't figure out how to get rid of EXEC_BAD_INSTRUCTION when calling MusicSequenceBarBeatTimeToBeats.
I have tried a lot of different solutions found on internet, but nothing seems to work.
My first try that didn't result an compile error was:
import Cocoa
import AudioToolbox
var musicSequence = MusicSequence()
NewMusicSequence(&musicSequence)
var barBeatTime = CABarBeatTime(bar: 1, beat: 1, subbeat: 0, subbeatDivisor: 960, reserved: 0)
var musicTimeStamp: MusicTimeStamp = 0
MusicSequenceBarBeatTimeToBeats(musicSequence, &barBeatTime, &musicTimeStamp)
The result is: EXEC_BAD_INSTRUCTION (code=1, address=0xe) at the MusicSequenceBarBeatTimeToBeats code row
Then I tried with this, but with same result:
var barBeatTime = CABarBeatTime(bar: 1, beat: 1, subbeat: 0, subbeatDivisor: 960, reserved: 0)
var musicTimeStamp = UnsafeMutablePointer<MusicTimeStamp>.alloc(sizeof(MusicTimeStamp))
MusicSequenceBarBeatTimeToBeats(musicSequence, &barBeatTime, musicTimeStamp)
musicTimeStamp.dealloc(sizeof(MusicTimeStamp))
I have tried the withUnsafeutablePointer function, but with same runtime error:
var barBeatTime = CABarBeatTime(bar: 1, beat: 1, subbeat: 0, subbeatDivisor: 960, reserved: 0)
var musicTimeStamp: MusicTimeStamp = 0
withUnsafeMutablePointer(&musicTimeStamp,
{
MusicSequenceBarBeatTimeToBeats(musicSequence, &barBeatTime, UnsafeMutablePointer($0))
})
If I pass nil in the third parameter it doesn't crash, but this is useless because the output is missing. So it seem to be the UnsafeMutablePointer<MusicTimeStamp> output parameter that is the problem.
MusicSequenceBarBeatTimeToBeats(musicSequence, &caBarBeatTime, nil)
Any suggestions?

Why don't I get the result of this Metal kernel

I am trying to understand how Metal compute shaders work, so I have wrote this code :
class AppDelegate: NSObject, NSApplicationDelegate {
var number:Float!
var buffer:MTLBuffer!
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
let metalDevice = MTLCreateSystemDefaultDevice()!
let library = metalDevice.newDefaultLibrary()!
let commandQueue = metalDevice.newCommandQueue()
let commandBuffer = commandQueue.commandBuffer()
let commandEncoder = commandBuffer.computeCommandEncoder()
let pointlessFunction = library.newFunctionWithName("pointless")!
let pipelineState = try! metalDevice.newComputePipelineStateWithFunction(pointlessFunction)
commandEncoder.setComputePipelineState(pipelineState)
number = 12
buffer = metalDevice.newBufferWithBytes(&number, length: sizeof(Float), options: MTLResourceOptions.StorageModeShared)
commandEncoder.setBuffer(buffer, offset: 0, atIndex: 0)
commandEncoder.endEncoding()
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
let data = NSData(bytesNoCopy: buffer.contents(), length: sizeof(Float), freeWhenDone: false)
var newResult:Float = 0
data.getBytes(&newResult, length: sizeof(Float))
print(newResult)
}
By making a buffer with StorageModeShared, I want changes made to the Metal buffer reflected in my Swift code, but when I populate my newResult variable, it looks like the buffer is still the same value than at the beginning (12) while it should be 125 :
#include <metal_stdlib>
using namespace metal;
kernel void pointless (device float* outData [[ buffer(0) ]]) {
*outData = 125.0;
}
What am I doing wrong ?
A kernel function doesn't run unless you dispatch it. I think you're assuming if you have a function, then Metal should run it one time, until you say otherwise, but that won't happen. It will instead not run at all. Add this before endEncoding and you're good to go!
let size = MTLSize(width: 1, height: 1, depth: 1)
commandEncoder.dispatchThreadgroups(size, threadsPerThreadgroup: size)

Using SecKeychainCreate from Swift

I am writing an OS X app that should maintain a custom Keychain, I am trying to use the Security framework's API to create the Keychain, however, I can't seem to get it to compile under Swift.
Here's what I have, assume that path contains a path to a potentially existing Keychain:
let pathName = (path as NSString).UTF8String
var keychain: Unmanaged<SecKeychain>?
var status = withUnsafeMutablePointer(&keychain) { pointer in
SecKeychainOpen(pathName, pointer)
}
if status != errSecSuccess {
status = withUnsafeMutablePointer(&keychain) { pointer in
SecKeychainCreate(pathName, UInt32(0), nil, false, nil, pointer)
}
}
The compiler is complaining about the types in the SecKeychainCreate call, however, I fail to understand what am I doing wrong.
Cannot invoke 'withUnsafeMutablePointer' with an argument list of type '(inout Unmanaged<SecKeychain>?, (_) -> _)'
If I modify the second closure slightly, I get this compiler error:
Cannot invoke 'SecKeychainCreate' with an argument list of type '(UnsafePointer<Int8>, UInt32, nil, Bool, nil, (UnsafeMutablePointer<Unmanaged<SecKeychain>?>))'
I appreciate all suggestions.
The promptUser parameter of SecKeychainCreate() has the type
Boolean, which is a "Mac OS historic type" and an alias to UInt8,
so it is different from the Swift Bool in Swift 1.2.
(Compare Type 'Boolean' does not conform to protocol 'BooleanType' for a similar issue.)
This means that you have to
pass Boolean(0) instead of false:
SecKeychainCreate(pathName, UInt32(0), nil, Boolean(0), nil, pointer)
Additional remarks:
withUnsafeMutablePointer() is not needed, you can pass &keychain
to the keychain functions.
(path as NSString).UTF8String is not needed, you can pass a Swift
string to a C function expecting a const char * parameter,
compare String value to UnsafePointer<UInt8> function parameter behavior.
Passing nil as password to SecKeychainCreate() is only allowed
if promptUser is TRUE, otherwise it causes a
"parameter error (-50)".
SecKeychainOpen() succeeds even if the keychain file does not
exists. According to the documentation, you have to check
SecKeychainGetStatus(). Alternatively, you can try to create
the keychain file first, as for example in Open Local Items Keychain?.
Together:
let path = "/path/to/my.keychain"
var keychain: Unmanaged<SecKeychain>?
var status = SecKeychainCreate(path, 0, "", Boolean(0), nil, &keychain)
if status == OSStatus(errSecDuplicateKeychain) {
status = SecKeychainOpen(path, &keychain)
}
As of Swift 2 / Xcode 7 beta 5, the Mac type Boolean is mapped
to Swift as Bool, and the key chain functions do no longer return
unmanaged objects:
let path = "/path/to/my.keychain"
var keychain: SecKeychain?
var status = SecKeychainCreate(path, 0, "", false, nil, &keychain)
if status == OSStatus(errSecDuplicateKeychain) {
status = SecKeychainOpen(path, &keychain)
}

Differences between Playground and Project

In the course of answering another question, I came across a weird bug in Playground. I have the following code to test if an object is an Array, Dictionary or a Set:
import Foundation
func isCollectionType(value : AnyObject) -> Bool {
let object = value as! NSObject
return object.isKindOfClass(NSArray)
|| object.isKindOfClass(NSDictionary)
|| object.isKindOfClass(NSSet)
}
var arrayOfInt = [1, 2, 3]
var dictionary = ["name": "john", "age": "30"]
var anInt = 42
var aString = "Hello world"
println(isCollectionType(arrayOfInt)) // true
println(isCollectionType(dictionary)) // true
println(isCollectionType(anInt)) // false
println(isCollectionType(aString)) // false
The code worked as expected when I put it into a Swift project or running it from the command line. However Playground wouldn't compile and give me the following error on the downcast to NSObject:
Playground execution failed: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0x7fb1d0f77fe8).
* thread #1: tid = 0x298023, 0x00007fb1d0f77fe8, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fb1d0f77fe8)
* frame #0: 0x00007fb1d0f77fe8
frame #1: 0x000000010ba46e12 libswiftCore.dylib`Swift._EmptyArrayStorage._withVerbatimBridgedUnsafeBuffer (Swift._EmptyArrayStorage)<A>((Swift.UnsafeBufferPointer<Swift.AnyObject>) -> A) -> Swift.Optional<A> + 50
The build platform was OS X in all three cases. Does anyone know how to get Playground to play along?
Xcode 6.3.2. Swift 1.2. OS X 10.10.3 Yosemite
Not really the cause of that bug (it does look weird) but...
You will need to use optional chaining since value can be AnyObject:
import Foundation
func isCollectionType(value : AnyObject) -> Bool {
if let object = value as? NSObject {
return object.isKindOfClass(NSArray)
|| object.isKindOfClass(NSDictionary)
|| object.isKindOfClass(NSSet)
}
return false
}
var arrayOfInt = [1, 2, 3]
var dictionary = ["name": "john", "age": "30"]
var anInt = 42
var aString = "Hello world"
isCollectionType(arrayOfInt)
isCollectionType(dictionary)
isCollectionType(anInt)
isCollectionType(aString)
Also worth noting, NSArray and Array are different things:
NSArray is an immutable class:
#interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
whilst Array is a struct:
struct Array<T> : MutableCollectionType, Sliceable, _DestructorSafeContainer
With this in mind it might be surprising that isCollectionType(arrayOfInt) returns true - but there is a conversion happening.

Swift _ABSearchComparison is not convertible to ABSearchComparison

Hi I am very new to programming and Swift and I am stuck with the search of the Address Book.
I get this error: _ABSearchComparison is not convertible to ABSearchComparison
var adbk = ABAddressBook.sharedAddressBook()
var isGroupBusiness = ABGroup.searchElementForProperty(kABGroupNameProperty, label: nil, key: nil, value: "Business", comparison: kABEqual)
thank you in advance
kABEqual has the type struct _ABSearchComparison and must therefore
by converted explicitly to an ABSearchComparison (aka CFIndex),
as expected by the comparison: parameter:
var isGroupBusiness = ABGroup.searchElementForProperty(kABGroupNameProperty,
label: nil, key: nil, value: "Business",
comparison: ABSearchComparison(kABEqual.rawValue))

Resources