Accessing Objective-C Pointers in Swift - objective-c

I have this Objective-C Code fragment, which I want to express in Swift
CFArrayRef windowList;
AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute, (CFTypeRef *)&windowList);
if ((!windowList) || CFArrayGetCount(windowList)<1)
continue;
AXUIElementRef windowRef = (AXUIElementRef) CFArrayGetValueAtIndex( windowList, 0);
CFTypeRef role;
AXUIElementCopyAttributeValue(windowRef, kAXRoleAttribute, (CFTypeRef *)&role);
The first thing I´m not sure about: Who allocates the memory behind the windowListPointer.
I tried with this fragment:
var windowListPointer : UnsafeMutablePointer<Optional<AnyObject>>
AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, windowListPointer );
But that does not even compile: It complains, the windowListPointer is not initialised.
What Object I could create, to let the WindowListPointer point to?

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) {
// ...
}
}
}

CFArray is the Foundation C version of NSArray (since C doesn't understand Objective C NSObjects). Swift papers over both NSArray and CFArray for you so you don't need to use a pointer; you should just be able to cast it to a Swift array of the appropriate type with as?

Related

Could not cast value of type XX to XX in swift 3

In Swift 3 contains method is always giving error. In the below code if annotation is MKAnnotation is passed and goest to next line. Then it gives error. I have searched a lot but not able to find the problem. Any solution for this issue?
Class declaration:
open class FBAnnotation : NSObject {
open var coordinate = CLLocationCoordinate2D(latitude: 52.0936440, longitude: 4.3592340)
open var title: String? = ""
open var annotationIndex: Int?
}
extension FBAnnotation : MKAnnotation {
}
Usage:
do {
if annotation is MKAnnotation {
if try node.annotations.contains(where: annotation as! (MKAnnotation) throws -> Bool) {
try node.annotations.remove(at: node.annotations.index(where: annotation as! (MKAnnotation) throws -> Bool)!)
node.count -= 1
return true
}
}
} catch {
return false
}
This works in a playground, no casting required. You cannot pass an annotation as the where parameter. You must pass in a function that declares whether or not the annotation is the one you are looking for. Here I consider them a match if they have the same coordinates, although your match criteria may be different.
var annotations = [MKAnnotation]()
var annotation: Any? = nil
if let annotation = annotation as? MKAnnotation {
if let index = annotations.index(where: {
$0.coordinate.latitude == annotation.coordinate.latitude &&
$0.coordinate.longitude == annotation.coordinate.longitude
}) {
annotations.remove(at: index)
}
}

Trying port Obj-C code to Swift that checks if keys exist in dict and values have correct type

Okay, here is some Objective C code I've been using in the past to quickly check if a dictionary contains certain key/value pairs and if the values are of the right type (have the expected class).
First I need a little helper class:
#interface TypeCheck : NSObject
#property NSString * name;
#property Class type;
#end
#implementation TypeCheck
+ (instancetype)typeCheckWitName:(NSString *)name type:(Class)type {
TypeCheck * tc = [[self alloc] init];
tc.name = name;
tc.type = type;
return tc;
}
#end
And then I can define keys and types like this:
NSArray<TypeCheck *> * model = #[
[TypeCheck typeCheckWitName:#"firstName" type:[NSString class]],
[TypeCheck typeCheckWitName:#"lastName" type:[NSString class]],
[TypeCheck typeCheckWitName:#"age" type:[NSNumber class]],
[TypeCheck typeCheckWitName:#"image" type:[NSImage class]]
// ... Many more follow ...
];
I was able to use structs for all that prior to ARC but with ARC the compiler doesn't like objects in structs, so I now use objects for everything. The final check code just looks like this:
for (TypeCheck * typeCheck in model) {
id value = dict[typeCheck.name];
if (!value) {
// BAD... Value must be there
// Throw error
return;
}
if (![value isKindOfClass:typeCheck.type]) {
// BAD... Value must be of right type
// Throw error
return;
}
// Do something with value
}
This used to be pretty nice code IMHO. Gets even nicer if you use a C function to create the TypeCheck objects:
#define TypeString [NSString class]
#define TypeNumber [NSNumber class]
#define TypeImage [NSImage class]
static TypeCheck * makeTypeCheck ( NSString * name, Class type ) {
return [TypeCheck typeCheckWitName:name type:type];
}
And then:
NSArray<TypeCheck *> * model = #[
makeTypeCheck(#"firstName", TypeString),
makeTypeCheck(#"lastName", TypeString),
makeTypeCheck(#"age", TypeNumber),
makeTypeCheck(#"image", TypeImage)
// ... and so on ...
One could even make makeTypeCheck a macro.
And now I'm trying to do the same or similar in Swift... and I fail horribly! I tried with a struct but how can I store class types there? I don't want to use Any as a type qualifier. Then I tried with a generic struct, like struct TypeCheck<T> so I could set the type, but I cannot put multiple of these into a single array as when T is different, as these are effectively different types (and again, I don't want to use Array<Any> despite that how can I cast? I cannot cast to TypeCheck without a generic type). I don't have to use a struct, an object will be fine but that doesn't really solve any of my problems. I cannot believe that this is so hard to do in Swift. I'm not really a Swift expert yet, so I guess i must be missing something important here.
While Obj-C was good at dynamic type inspection, Swift is much better of you allow the compiler to do the type checking at compile time. Since I don't know what your specific use case is, I'd encourage you to look for a more Swifty way to do what you want instead of just converting Obj-C to Swift. But since I don't know your use case, I'll just answer your question as written.
The only way I could get something like you describe was to make the struct conform to a protocol. Then when you put it in an array, you set the arrays type to contain instances of the protocol.
protocol TypeCheckable {
var name: String { get }
func matches(thing: Any) -> Bool
}
struct TypeCheck<T>: TypeCheckable {
let name: String
init(name: String, type: T.Type) {
self.name = name
}
func matches(thing: Any) -> Bool {
return thing is T
}
}
let array: [TypeCheckable] = [
TypeCheck(name: "test", type: String.self),
TypeCheck(name: "other", type: Int.self)
]
If you define this:
typealias TypeChecker = ([String: AnyObject]) -> Bool
struct makeTypeCheck<T> {
let name: String
func checker() -> TypeChecker {
return { (dict: [String: AnyObject]) -> Bool in
guard let v = dict[self.name] else {
return false
}
if let _ = v as? T {
return true
}
return false
}
}
}
func checkDictionary(dict: [String: AnyObject], model: [TypeChecker]) -> Bool {
for m in model {
if !m(dict) {
return false
}
}
return true
}
This test passes
func testChecker() {
let model = [
makeTypeCheck<String>(name: "firstName").checker(),
makeTypeCheck<Int>(name: "age").checker(),
]
XCTAssertTrue(checkDictionary(["firstName": "Jane", "age": 35], model: model))
XCTAssertFalse(checkDictionary(["firstName": 21, "age": 35], model: model))
XCTAssertFalse(checkDictionary(["age": 35], model: model))
}

Swift: write a function that allocates an instance of (any) class

I'm looking for the equivalent of the following Obj-C code in Swift:
- newInstanceOf:(id)classRef {
return [classRef new];
}
and then to use it:
id instance = [whatever newInstanceOf:NSArray.class]
[instance isKindOfClass:NSArray.class] == YES
I have tried using a Swift template:
func newSomething<T>(classRef:T.Type) -> T {
return classRef()
}
I get the error: error: 'T' cannot be constructed because it has no accessible initializers
You could create a protocol to act as a type constraint for objects initializable by a void-argument initializer, and thereafter extend your types of choice to this protocol.
protocol SimplyInitializable {
init()
}
extension Int : SimplyInitializable { }
extension Double : SimplyInitializable { }
extension String : SimplyInitializable { }
struct MyStruct {
var myInt : Int
init() {
myInt = 0
}
}
extension MyStruct : SimplyInitializable { }
func newSomething<T: SimplyInitializable>(classRef: T.Type) -> T {
return classRef.init()
}
/* Examples */
var a = newSomething(Int)
var b = newSomething(Double)
var c = newSomething("".dynamicType)
var d = newSomething(MyStruct)
var e = newSomething(a.dynamicType)
print(a.dynamicType) // Int
print(b.dynamicType) // Double
print(c.dynamicType) // String
print(d.dynamicType) // MyStruct
print(e.dynamicType) // Int
Actually in Swift, not all classes are guaranteed to have an init() initializer. It can work with NSObject classes though because NSObject does have that requirement.
func newInstanceOf<T:NSObject>(aClass:T.Type) -> NSObject
{ return aClass.init() }
let string = newInstanceOf(NSString) // ""
let date = newInstanceOf(NSDate) // 2016-01-15 05:27:29 +0000

Accessing items in UIDynamicItemBehavior with Optional return value

I want to rewrite this Objective-C method in Swift.
I'm trying to find the best way to do it.
- (UIDynamicItemBehavior*) itemBehaviourForView:(UIView*)view
{
for (UIDynamicItemBehavior* behaviour in _animator.behaviors)
{
if (behaviour.class == [UIDynamicItemBehavior class] && [behaviour.items firstObject] == view)
{
return behaviour;
}
}
return nil;
}
I wrote something like that:
func itemBehaviorForView(view :UIView)->UIDynamicItemBehavior
{
for dynamicItemBehavior in animator.behaviors
{
if dynamicItemBehavior is UIDynamicItemBehavior && dynamicItemBehavior.items.firstObject == view
{
return dynamicItemBehavior as UIDynamicItemBehavior
}
}
return nil
}
I see two problems:
dynamicItemBehavior.items.firstObject is not Array, so there is no firstObject method
I cannot return nil
What should I do about these?
If there is a possibility that the function will return nil then the function's return type needs to be an optional. In your case declare the function as:
func itemBehaviorForView (view:UIView) -> UIDynamicItemBehavior?
The documentation for UIDynamicItemBehavior declares items as an array with:
var items: [AnyObject]! { get }
and thus you would reference the first object using array subscript notation as:
dynamicItemBehavior.items[0]
Of course, the items might be empty. To handle that in idiomatic Swift use:
if dynamicItemBehavior is UIDynamicItemBehavior {
if let firstView = dynamicItemBehavior.items?[0] {
if firstView == view {
return dynamicItemBehavior as UIDynamicItemBehavior
}
}
}
where the use of if let <var> will bind <var> iff the result of ...items? is not nil.
More functional approach after conversion:
let r = (animator.behaviors.filter { $0 is UIDynamicItemBehavior } as [UIDynamicItemBehavior])
.filter({ $0.items?[0] === view })
return r.count > 0 ? r[0] : nil
And we can even shrink it to one line return if we bridgeToObjectiveC() the result to take advantage of firstObject property:
return (animator.behaviors.filter { $0 is UIDynamicItemBehavior } as [UIDynamicItemBehavior])
.filter({ $0.items?[0] === view }).bridgeToObjectiveC().firstObject as? UIDynamicItemBehavior
Remarks:
Objective-C == to compare references in Swift achieved with ===.
I know that initial Objective-C algorithm was eager and returned as soon as match found. Show the expressiveness of functional approach.
I think Keenle was on the right track with using a functional style. But this is not a job for filter, this is a job for find. It will stop early on the first match it encounters. Unfortunately Swift does not currently implement find for us (unlike filter), but we can add it with extensions!
Unlike the other answers here, I don't know the type of animator or behaviors. I'm going to assume that behaviors is an NSArray, if that assumption is incorrect, please let me know.
extension NSArray {
func find(predicate: (AnyObject) -> Bool) -> AnyObject? {
for element: AnyObject in self {
if predicate(element) {
return element
}
}
return nil
}
}
Now we just have to update your function to use this!
func itemBehaviorForView(view: UIView) -> UIDynamicItemBehavior?
{
func predicate(object: AnyObject) -> Bool {
if let dynamicItemBehavior = object as? UIDynamicItemBehavior {
return view === dynamicItemBehavior.items?[0]
}
return false
}
return animator.behaviors.find(predicate) as? UIDynamicItemBehavior
}
I will admit, the casting on the final return statement is a little bit ugly. If animator.behaviors was know to only contains objects of the acceptable return type we could avoid this, but you're likely stuck with this because of the obj-c code.

Cast closures/blocks

In Objective-C, I often pass around blocks. I use them very often to implement patterns that help avoid storing stuff into instance variables, thus avoiding threading/timing issues.
For example, I assign them to a CAAnimation via -[CAAnimation setValue:forKey:] so I can execute the block when the animation is finished. (Objective-C can treat blocks as objects; you also can do [someBlock copy] and [someBlock release].)
However, trying to use these patterns in Swift together with Objective-C seems to be very difficult. (Edit: and we can see that the language is still in flux: have adapted the code so it works on Xcode6-beta2, previous version worked on Xcode6-beta1.)
For example, I can't convert AnyObject back to a block/closure. The following yields an error from the compiler:
override func animationDidStop(anim: CAAnimation!, finished flag: Bool)
{
let completion : AnyObject! = anim.valueForKey("completionClosure")
(completion as (#objc_block ()->Void))()
// Cannot convert the expression's type 'Void' to type '#objc_block () -> Void'
}
I have found a workaround, but it's pretty ugly, IMHO: in my bridging header, I have:
static inline id blockToObject(void(^block)())
{
return block;
}
static inline void callBlockAsObject(id block)
{
((void(^)())block)();
}
And now I can do this in Swift:
func someFunc(completion: (#objc_block ()->Void))
{
let animation = CAKeyframeAnimation(keyPath: "position")
animation.delegate = self
animation.setValue(blockToObject(completion), forKey: "completionClosure")
…
}
override func animationDidStop(anim: CAAnimation!, finished flag: Bool)
{
let completion : AnyObject! = anim.valueForKey("completionClosure")
callBlockAsObject(completion)
}
It works, but I'd need a new function for every block type that I'd like to use and I'm hacking around the compiler which can't be good either.
So is there a way to solve this in a pure Swift way?
How about a generic Block parameterized with the function type?
class Block<T> {
let f : T
init (_ f: T) { self.f = f }
}
Allocate one of these; it will be a subtype of AnyObject and thus be assignable into dictionaries and arrays. This doesn't seem too onerous especially with the trailing closure syntax. In use:
5> var b1 = Block<() -> ()> { print ("Blocked b1") }
b1: Block<() -> ()> = {
f = ...
}
6> b1.f()
Blocked b1
and another example where the Block type is inferred:
11> var ar = [Block { (x:Int) in print ("Block: \(x)") }]
ar: [Block<(Int) -> ()>] = 1 value {
[0] = {
f = ...
}
}
12> ar[0].f(111)
Block: 111
I like GoZoner's solution - wrap the block in a custom class - but since you asked for the actual "Swift way" to perform the cast between a block and an AnyObject, I'll just give the answer to that question: cast with unsafeBitCast. (I'm guessing that this is more or less the same as Bryan Chen's reinterpretCast, which no longer exists.)
So, in my own code:
typealias MyDownloaderCompletionHandler = #objc_block (NSURL!) -> ()
Note: in Swift 2, this would be:
typealias MyDownloaderCompletionHandler = #convention(block) (NSURL!) -> ()
Here's the cast in one direction:
// ... cast from block to AnyObject
let ch : MyDownloaderCompletionHandler = // a completion handler closure
let ch2 : AnyObject = unsafeBitCast(ch, AnyObject.self)
Here's the cast back in the other direction:
// ... cast from AnyObject to block
let ch = // the AnyObject
let ch2 = unsafeBitCast(ch, MyDownloaderCompletionHandler.self)
// and now we can call it
ch2(url)
Here's yet another solution, allowing us to cast to exchange values with Objective-C. It builds on GoZoner's idea of wrapping the function in a class; the difference is our class is an NSObject subclass, and can thus give the function Objective-C block memory management without any hackery, and can be directly used as an AnyObject and handed over to Objective-C:
typealias MyStringExpecter = (String) -> ()
class StringExpecterHolder : NSObject {
var f : MyStringExpecter! = nil
}
Here's how to use it to wrap a function and pass where an AnyObject is expected:
func f (s:String) {println(s)}
let holder = StringExpecterHolder()
holder.f = f
let lay = CALayer()
lay.setValue(holder, forKey:"myFunction")
And here's how to extract the function later and call it:
let holder2 = lay.valueForKey("myFunction") as StringExpecterHolder
holder2.f("testing")
All you need to do is use reinterpretCast to perform force cast.
(reinterpretCast(completion) as (#objc_block Void -> Void))()
from REPL
1> import Foundation
2> var block : #objc_block Void -> Void = { println("test")}
block: #objc_block Void -> Void =
3> var obj = reinterpretCast(block) as AnyObject // this is how to cast block to AnyObject given it have #objc_block attribute
obj: __NSMallocBlock__ = {}
4> var block2 = reinterpretCast(obj) as (#objc_block Void -> Void)
block2: (#objc_block Void -> Void) =
5> block2()
test
6>