Re: Passing a swift function to objective-c

2014-10-18 Thread Kevin Meaney
Hi Roland,

Thanks for the followup. I've created a proper git rep on github rather than 
just a gist. Most of my github reps seem to be this kind of mini demonstration 
project and I was trying to avoid yet another one.

https://github.com/SheffieldKevin/swift-objectivec

 What version of Xcode are you using by the way, Swift is so flux-y at the 
 moment it probably makes a difference. 

I'm now running release Yosemite and release Xcode 6.1. That appears to me to 
make no difference.

I still can't assign to the optional property of my protocol.

You can ignore the ImageProvider2 class, I've just included it for 
completeness. It doesn't have a protocol and just declares the property itself.

So with my protocol I've done something similar to what you did if I've 
interpreted your discussion correctly. I've got two properties, one that is 
required and one that is optional.

Everything works fine for the required property. But I still can't get the 
optional one to work.

In ImageProvider.m you'll see that the MakeImageProvider function assigns a 
block to the optional property and in SupplyCreateImage.swift I've commented 
out the assignment. I've provided the example this way so that it can be seen 
that it works when done using objective-c. But if you comment out the 
assignment to the optional property of the block, and uncomment the line in the 
swift file you'll see that the command line tool no longer compiles.

Like you I've tried the use of the optional and playing around with casting but 
I've not actually got the code to compile this way.

Kevin


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Passing a swift function to objective-c

2014-10-18 Thread Kevin Meaney
I've now found an acceptable solution.

Rather than a property I've added an optional method to the protocol which then 
in its implementation assigns using the property, pretty much to make sure that 
the function/block is copied. I declared the method like so:

-(void)applyMyCreateImageFunction:(CGImageRef (^)(NSDictionary 
*))createImageFunction

And when calling it from the swift code I call it like so:

imageProvider.applyMyCreateImageFunction?(makeImage)

The question mark was necessary to evaluate whether the optional protocol 
method had been implemented or not.

Kevin

On 18 Oct 2014, at 18:18, Kevin Meaney k...@yvs.eu.com wrote:

 Hi Roland,
 
 Thanks for the followup. I've created a proper git rep on github rather than 
 just a gist. Most of my github reps seem to be this kind of mini 
 demonstration project and I was trying to avoid yet another one.
 
 https://github.com/SheffieldKevin/swift-objectivec
 
 What version of Xcode are you using by the way, Swift is so flux-y at the 
 moment it probably makes a difference. 
 
 I'm now running release Yosemite and release Xcode 6.1. That appears to me to 
 make no difference.
 
 I still can't assign to the optional property of my protocol.
 
 You can ignore the ImageProvider2 class, I've just included it for 
 completeness. It doesn't have a protocol and just declares the property 
 itself.
 
 So with my protocol I've done something similar to what you did if I've 
 interpreted your discussion correctly. I've got two properties, one that is 
 required and one that is optional.
 
 Everything works fine for the required property. But I still can't get the 
 optional one to work.
 
 In ImageProvider.m you'll see that the MakeImageProvider function assigns a 
 block to the optional property and in SupplyCreateImage.swift I've commented 
 out the assignment. I've provided the example this way so that it can be seen 
 that it works when done using objective-c. But if you comment out the 
 assignment to the optional property of the block, and uncomment the line in 
 the swift file you'll see that the command line tool no longer compiles.
 
 Like you I've tried the use of the optional and playing around with casting 
 but I've not actually got the code to compile this way.
 
 Kevin
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 https://lists.apple.com/mailman/options/cocoa-dev/ktam%40yvs.eu.com
 
 This email sent to k...@yvs.eu.com


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Passing a swift function to objective-c

2014-10-17 Thread Kevin Meaney
Thanks Roland.

On 17 Oct 2014, at 00:20, Roland King r...@rols.org wrote:
 
 On 17 Oct 2014, at 6:13 am, Kevin Meaney k...@yvs.eu.com wrote:
 
 Hi,
 
 I'm beginning to feel this above my pay grade as I can't seem to work it out.
 
 I have a framework in Objective-C. I've been writing some tests for it, and 
 to make life fun I've been writing the tests in Swift.
 
 I have a property of a class in the objective-c framework declared like so:
 
 @property (nonatomic, copy) CGImageRef (^createImage)(NSDictionary *);
 
 In my tests I'm trying to write a function that I can assign to the property.
 
 In the most basic form the function looks like this, I'm ignoring the passed 
 in dictionary for the purposes of asking this question:
 
 func createCGImage2(dictionary: [NSObject:AnyObject]) - CGImage {
let jpegURL = NSBundle.mainBundle().URLForResource(myimage, 
 withExtension:jpg)
let imageSource = CGImageSourceCreateWithURL(jpegURL, nil)!
let theImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil)
return theImage
 }
 
 When I try to set the property with the function I get:
 
 error: cannot convert the expression's type '([NSObject : AnyObject]) - 
 UnmanagedCGImage!' to type '(([NSObject : AnyObject]!) - 
 UnmanagedCGImage!)!?'
 
 Now, if I have a function declared like so:
 
 func createCGImageFromDictionary(dictionary: [NSObject:AnyObject]!) - 
 UnmanagedCGImage!
 
 error: cannot convert the expression's type '([NSObject : AnyObject]!) - 
 UnmanagedCGImage!' to type '(([NSObject : AnyObject]!) - 
 UnmanagedCGImage!)!?'
 
 I'm still a long way off. There's an extra () in there and an extra !? at 
 the end that I really don't know how to interpret. Also I don't know how to 
 convert the result of CGImageSourceCreateImageAtIndex to a 
 UnmanagedCGImage as a return value.
 
 I've been through various bits of the documentation, but something isn't 
 clicking so that I understand how this stuff works so that I can try and 
 solve it.
 
 Kevin
 
 __
 
 ok this simple test works for me .. I also don’t understand the extra parens 
 etc in your example. So where does your code differ from the below? Note I 
 set it both with a public function and a closure, just to see if it works.

A detail I should have included. The @property is declared in the optional 
section of a protocol. I know the object in question has implemented the 
property. But that explains the extra requirements for unwrapping.

I've put together a gist where I've attempted to play with this.

https://gist.github.com/SheffieldKevin/a06907e163885f249548

I got the assigning to a property working when that property was declared as 
part of the class, but not when it has been declared in the optional section of 
a protocol. So I was able to duplicate what you did Roland. But no matter what 
I try, documentation I read I can't make it work when the property is declared 
in the protocol.

I got myself distracted because the project I setup to try out stuff was an 
objective-c command line tool and I also had trouble calling swift code from 
Objective-c. I could not get a swift function that wasn't a class or instance 
method to be callable from Objective-c.

Kevin

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Passing a swift function to objective-c

2014-10-17 Thread Quincey Morris
On Oct 17, 2014, at 09:59 , Kevin Meaney k...@yvs.eu.com wrote:
 
 I got the assigning to a property working when that property was declared as 
 part of the class, but not when it has been declared in the optional section 
 of a protocol. So I was able to duplicate what you did Roland. But no matter 
 what I try, documentation I read I can't make it work when the property is 
 declared in the protocol.

Presumably, the issue is that Swift makes assumptions about the possibility of 
a nil value when translating Obj-C frameworks types in a header. I believe that 
trying to guess the Swift translation from the Obj-C declaration will just 
drive you into madness. What you need to do instead is examine the translated 
declaration. Try Command-clicking on the protocol name in the place where you 
declare conformance, and you should see the translation. Then mimic the block 
type you see there.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Passing a swift function to objective-c

2014-10-17 Thread Roland King
 
 ok this simple test works for me .. I also don’t understand the extra parens 
 etc in your example. So where does your code differ from the below? Note I 
 set it both with a public function and a closure, just to see if it works.
 
 A detail I should have included. The @property is declared in the optional 
 section of a protocol. I know the object in question has implemented the 
 property. But that explains the extra requirements for unwrapping.
 
 I've put together a gist where I've attempted to play with this.
 
 https://gist.github.com/SheffieldKevin/a06907e163885f249548 
 https://gist.github.com/SheffieldKevin/a06907e163885f249548
 
 I got the assigning to a property working when that property was declared as 
 part of the class, but not when it has been declared in the optional section 
 of a protocol. So I was able to duplicate what you did Roland. But no matter 
 what I try, documentation I read I can't make it work when the property is 
 declared in the protocol.
 
 I got myself distracted because the project I setup to try out stuff was an 
 objective-c command line tool and I also had trouble calling swift code from 
 Objective-c. I could not get a swift function that wasn't a class or instance 
 method to be callable from Objective-c.
 
 Kevin
 

Right the optionality in the protocol is somewhat important and yes that does 
explain why there’s the extra parens and ? around it. You’re certainly out in 
some deeper water here with optional properties in a protocol which return 
blocks in objective C being bridged over to Swift. 

I can’t get your error message however. The stuff you posted on github might be 
helpful if it were a full project, with xcode project file, which exhibits that 
error message when built, ie it doesn’t actually build. I just can’t make it 
fail. What version of Xcode are you using by the way, Swift is so flux-y at the 
moment it probably makes a difference. 

I made my own protocol with an optional (and a non-optional) property and used 
it in Swift and I can assign to either of them with the method posted earlier 
in the thread. I can actually defeat the compiler in a few ways, most notably 
by casting to the protocol itself in which case it won’t let me assign the 
property at all. 

I thought of this …

x.createImage? = function

but that doesn’t work either. If x does implement createImage() but returns nil 
because it’s not set yet then it doesn’t set it, if x doesn’t implement the 
getter then it just crashes. 

The one version I do have working is this piece of ugliness. Fruit is the 
protocol with the optional property, Banana is a fruit which may or may not 
implement it, I personally don’t like bananas at all. 

var x = Banana()
var y = x as Fruit

if y.createImage != nil
{
x.createImage = theImplementationOfCreateImage
let r = x.createImageOptional( nil )
}


The test on y appears to tell you whether or not the protocol is implemented on 
x. Then you can set the property on x inside the block, except you probably 
can’t because this is the place you’ve been having issues setting the property 
with an error message I can’t make happen. That code works fine for me, and 
calls the method (which then crashes because I sent it nil but that’s fine)

There’s probably a deeper issue here. createImage is a property name which 
itself implies two methods, one with the same name as the property, the other 
with ‘set’ stuffed on the front. Then the implementation of that property is 
itself optional. Then you pull all that over to Swift and have to disambiguate 
the case where you’re checking for implementation of the property and the case 
you’re getting it and checking if it’s set to nil or not and the case you want 
to set it to something, possibly back to nil. This may be one of those things 
which just doesn’t translate very well. 




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Passing a swift function to objective-c

2014-10-17 Thread Roland King
 
   let r = x.createImageOptional( nil )
 

is of course

let r = x.createImage( nil )

I had two properties in my test code and didn’t fix it when I copy/pasted it, 
sorry. 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Passing a swift function to objective-c

2014-10-16 Thread Roland King

 On 17 Oct 2014, at 6:13 am, Kevin Meaney k...@yvs.eu.com wrote:
 
 Hi,
 
 I'm beginning to feel this above my pay grade as I can't seem to work it out.
 
 I have a framework in Objective-C. I've been writing some tests for it, and 
 to make life fun I've been writing the tests in Swift.
 
 I have a property of a class in the objective-c framework declared like so:
 
 @property (nonatomic, copy) CGImageRef (^createImage)(NSDictionary *);
 
 In my tests I'm trying to write a function that I can assign to the property.
 
 In the most basic form the function looks like this, I'm ignoring the passed 
 in dictionary for the purposes of asking this question:
 
 func createCGImage2(dictionary: [NSObject:AnyObject]) - CGImage {
let jpegURL = NSBundle.mainBundle().URLForResource(myimage, 
 withExtension:jpg)
let imageSource = CGImageSourceCreateWithURL(jpegURL, nil)!
let theImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil)
return theImage
 }
 
 When I try to set the property with the function I get:
 
 error: cannot convert the expression's type '([NSObject : AnyObject]) - 
 UnmanagedCGImage!' to type '(([NSObject : AnyObject]!) - 
 UnmanagedCGImage!)!?'
 
 Now, if I have a function declared like so:
 
 func createCGImageFromDictionary(dictionary: [NSObject:AnyObject]!) - 
 UnmanagedCGImage!
 
 error: cannot convert the expression's type '([NSObject : AnyObject]!) - 
 UnmanagedCGImage!' to type '(([NSObject : AnyObject]!) - 
 UnmanagedCGImage!)!?'
 
 I'm still a long way off. There's an extra () in there and an extra !? at the 
 end that I really don't know how to interpret. Also I don't know how to 
 convert the result of CGImageSourceCreateImageAtIndex to a UnmanagedCGImage 
 as a return value.
 
 I've been through various bits of the documentation, but something isn't 
 clicking so that I understand how this stuff works so that I can try and 
 solve it.
 
 Kevin
 
 __

ok this simple test works for me .. I also don’t understand the extra parens 
etc in your example. So where does your code differ from the below? Note I set 
it both with a public function and a closure, just to see if it works. 

I think that’s how you get your Unmanaged object as well, but I’m not entirely 
sure. Swift seems to do better with some CoreFoundation types than others. 

Note that took far more time messing about with fiddly bits of syntax than I 
wish it had, and I’ve only not touched Swift for a week or so. 

obj-C bit, Banana.h

@interface Banana : NSObject
@property( nonatomic, copy ) CGImageRef(^createImage)(NSDictionary *dictionary);
@end


swift bit, Orange.swift

public func x( dict : [ NSObject:AnyObject]! ) - UnmanagedCGImageRef!
{
let jpegURL = NSBundle.mainBundle().URLForResource(myimage, 
withExtension:jpg)
let imageSource = CGImageSourceCreateWithURL(jpegURL, nil)!
let theImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil)
let x = Unmanaged.passUnretained(theImage);
x.autorelease()
return x
}

@objc public class Orange
{
var j = Banana()

public func doSomething()
{
j.createImage = x

j.createImage = {
(dict)-UnmanagedCGImageRef in
let jpegURL = 
NSBundle.mainBundle().URLForResource(myimage, withExtension:jpg)
let imageSource = CGImageSourceCreateWithURL(jpegURL, 
nil)!
let theImage = 
CGImageSourceCreateImageAtIndex(imageSource, 0, nil)
let x = Unmanaged.passUnretained(theImage);
x.autorelease()
return x
}
}
}









___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com