Thoughts on "Fully eliminate implicit bridging conversions from Swift"


(simon gladman) #1

Apologies for arriving a little late to the party and I hope this is a
suitable forum to discuss this subject. I've spent some time over the last
few days moving a large Core Image project to Swift 3.0 and come across
some side effects which I think are related to proposal SE-0072, *Fully
eliminate implicit bridging conversions from Swift*.

First off, rightly or wrongly, I've always typed the scalar parameters of
my subclassed *CIFilters* as *CGFloat*. It makes working with *CIVectors*
and *CGRects* cleaner and feels more "Swifty" than using *NSNumber*.
However, moving to Swift 3.0, using anything apart from an *NSNumber*
breaks. For example:

        let radius: CGFloat = 25

        let blur = CIFilter(

            name: "CIGaussianBlur",

            withInputParameters: [kCIInputRadiusKey: radius])

The same with passing arguments to a *CIKernel*, *CIWarpKernel* or
*CIColorKernel*:

        kernel.apply(

            withExtent: CGRect(x: 0, y: 0, width: 100, height: 100),

            arguments: [radius])

Secondly, the attributes property of a filter (of type *[String: AnyObject]*)
which I'd normally code along the lines of:

    override var attributes: [String : AnyObject]

    {

        return [

            "inputImage": [

                 kCIAttributeIdentity: 0,

                 kCIAttributeClass: "CIImage",

                 kCIAttributeDisplayName: "Image",

                 kCIAttributeType: kCIAttributeTypeScalar]

        ]

    }

...fails to compile. kCIAttributeTypeScalar is of type *String* and needs
to be cast to *NSString* and the dictionary itself needs to be cast to
*AnyObject*:

    override var attributes: [String : AnyObject]

    {

        return [

            "inputImage": [

                 kCIAttributeIdentity: 0,

                 kCIAttributeClass: "CIImage",

                 kCIAttributeDisplayName: "Image",

                 kCIAttributeType: kCIAttributeTypeScalar as NSString] as
AnyObject

        ]

    }

It seems awkward to me that the constant supplied by Core Image to describe
an attribute's type needs to be cast to another type to get it working.

Are these changes just something that we'll need to live with? Are they
still in flux? Have I totally misunderstood everything and there's a more
elegant solution?

Any thoughts would be greatly appreciated!

Simon

Simon Gladman +44 7973 669691

Blog: http://flexmonkey.blogspot.co.uk
GitHub: https://github.com/FlexMonkey
Twitter: @FlexMonkey <https://twitter.com/FlexMonkey>


(Charlie Monroe) #2

What error do you get (i.e. why doesn't it compile)?

Have you tried this?

let result: [String : AnyObject] = [
  "inputImage": [
    kCIAttributeIdentity: 0,
    kCIAttributeClass: "CIImage",
    kCIAttributeDisplayName: "Image",
    kCIAttributeType: kCIAttributeTypeScalar
  ]
]
return result

Charlie

···

On May 24, 2016, at 6:07 PM, simon gladman via swift-evolution <swift-evolution@swift.org> wrote:

Apologies for arriving a little late to the party and I hope this is a suitable forum to discuss this subject. I've spent some time over the last few days moving a large Core Image project to Swift 3.0 and come across some side effects which I think are related to proposal SE-0072, Fully eliminate implicit bridging conversions from Swift.

First off, rightly or wrongly, I've always typed the scalar parameters of my subclassed CIFilters as CGFloat. It makes working with CIVectors and CGRects cleaner and feels more "Swifty" than using NSNumber. However, moving to Swift 3.0, using anything apart from an NSNumber breaks. For example:

        let radius: CGFloat = 25
        
        let blur = CIFilter(
            name: "CIGaussianBlur",
            withInputParameters: [kCIInputRadiusKey: radius])

The same with passing arguments to a CIKernel, CIWarpKernel or CIColorKernel:

        kernel.apply(
            withExtent: CGRect(x: 0, y: 0, width: 100, height: 100),
            arguments: [radius])

Secondly, the attributes property of a filter (of type [String: AnyObject]) which I'd normally code along the lines of:

    override var attributes: [String : AnyObject]
    {
        return [
            "inputImage": [
                 kCIAttributeIdentity: 0,
                 kCIAttributeClass: "CIImage",
                 kCIAttributeDisplayName: "Image",
                 kCIAttributeType: kCIAttributeTypeScalar]
        ]
    }

...fails to compile. kCIAttributeTypeScalar is of type String and needs to be cast to NSString and the dictionary itself needs to be cast to AnyObject:

    override var attributes: [String : AnyObject]
    {
        return [
            "inputImage": [
                 kCIAttributeIdentity: 0,
                 kCIAttributeClass: "CIImage",
                 kCIAttributeDisplayName: "Image",
                 kCIAttributeType: kCIAttributeTypeScalar as NSString] as AnyObject
        ]
    }

It seems awkward to me that the constant supplied by Core Image to describe an attribute's type needs to be cast to another type to get it working.

Are these changes just something that we'll need to live with? Are they still in flux? Have I totally misunderstood everything and there's a more elegant solution?

Any thoughts would be greatly appreciated!

Simon

Simon Gladman +44 7973 669691 <tel:%2B44%207973%20669691>

Blog: http://flexmonkey.blogspot.co.uk <http://flexmonkey.blogspot.co.uk/>
GitHub: https://github.com/FlexMonkey
Twitter: @FlexMonkey <https://twitter.com/FlexMonkey>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(simon gladman) #3

Hi,

The error is get is "*Contextual type 'AnyObject' cannot be used with
dictionary literal*" - and I get the same issue with your approach.

With the CGFloat, I get "*Value of type 'CGFloat' does not conform to
expected dictionary value type 'AnyObject'*'".

Simon

Simon Gladman +44 7973 669691

Blog: http://flexmonkey.blogspot.co.uk
GitHub: https://github.com/FlexMonkey
Twitter: @FlexMonkey <https://twitter.com/FlexMonkey>

···

On 24 May 2016 at 17:18, Charlie Monroe <charlie@charliemonroe.net> wrote:

What error do you get (i.e. why doesn't it compile)?

Have you tried this?

let result: [String : AnyObject] = [
"inputImage": [
kCIAttributeIdentity: 0,
kCIAttributeClass: "CIImage",
kCIAttributeDisplayName: "Image",
kCIAttributeType: kCIAttributeTypeScalar
]
]
return result

Charlie

On May 24, 2016, at 6:07 PM, simon gladman via swift-evolution < > swift-evolution@swift.org> wrote:

Apologies for arriving a little late to the party and I hope this is a
suitable forum to discuss this subject. I've spent some time over the last
few days moving a large Core Image project to Swift 3.0 and come across
some side effects which I think are related to proposal SE-0072, *Fully
eliminate implicit bridging conversions from Swift*.

First off, rightly or wrongly, I've always typed the scalar parameters of
my subclassed *CIFilters* as *CGFloat*. It makes working with *CIVectors*
and *CGRects* cleaner and feels more "Swifty" than using *NSNumber*.
However, moving to Swift 3.0, using anything apart from an *NSNumber*
breaks. For example:

        let radius: CGFloat = 25

        let blur = CIFilter(
            name: "CIGaussianBlur",
            withInputParameters: [kCIInputRadiusKey: radius])

The same with passing arguments to a *CIKernel*, *CIWarpKernel* or
*CIColorKernel*:

        kernel.apply(
            withExtent: CGRect(x: 0, y: 0, width: 100, height: 100),
            arguments: [radius])

Secondly, the attributes property of a filter (of type *[String:
AnyObject]*) which I'd normally code along the lines of:

    override var attributes: [String : AnyObject]
    {
        return [
            "inputImage": [
                 kCIAttributeIdentity: 0,
                 kCIAttributeClass: "CIImage",
                 kCIAttributeDisplayName: "Image",
                 kCIAttributeType: kCIAttributeTypeScalar]
        ]
    }

...fails to compile. kCIAttributeTypeScalar is of type *String* and needs
to be cast to *NSString* and the dictionary itself needs to be cast to
*AnyObject*:

    override var attributes: [String : AnyObject]
    {
        return [
            "inputImage": [
                 kCIAttributeIdentity: 0,
                 kCIAttributeClass: "CIImage",
                 kCIAttributeDisplayName: "Image",
                 kCIAttributeType: kCIAttributeTypeScalar as NSString] as
AnyObject
        ]
    }

It seems awkward to me that the constant supplied by Core Image to
describe an attribute's type needs to be cast to another type to get it
working.

Are these changes just something that we'll need to live with? Are they
still in flux? Have I totally misunderstood everything and there's a more
elegant solution?

Any thoughts would be greatly appreciated!

Simon

Simon Gladman +44 7973 669691

Blog: http://flexmonkey.blogspot.co.uk
GitHub: https://github.com/FlexMonkey
Twitter: @FlexMonkey <https://twitter.com/FlexMonkey>

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution