"if let" syntax for legacy objective-c properties.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

"if let" syntax for legacy objective-c properties.

Samuel Williams
Hey everyone.

I'm working on a "legacy" objective-c codebase. It has code like this:

- (void)resetSheet:(id)sender {

if ([sender respondsToSelector:@selector(property)]) {

PMProperty * selectedProperty = [sender performSelector:@selector(property)];

if (selectedProperty) {

self.tenure.property = (PMProperty *)[self.managedObjectContext objectWithID:selectedProperty.objectID];

}

}

}


I'm trying to write something equivalent in Swift with the same incoming arguments. I'm writing this:

override func resetSheet(sender: AnyObject!) {

if let selectedProperty = sender.property {

self.propertyTransaction?.property = self.managedObjectContext.objectWithID(selectedProperty.objectID) as? PMProperty

}

}


I was under the impression that the `if let` syntax would check whether the condition was nil or not. But, when I run this code, if `sender.property` is nil, `selectedProperty` is nil and the if condition is executed branch is executed anyway. I assumed that the `if` statement wouldn't be executed if `selectedProperty` was nil. What am I doing wrong or mis-understanding? In this example, sender is always a valid object, and the type of sender.property is PMProperty!

Thanks
Samuel

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/140ad798-764b-44a5-8bd3-319b19e5e7ea%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: "if let" syntax for legacy objective-c properties.

Jens Alfke

On Sep 18, 2015, at 3:28 AM, Samuel Williams <[hidden email]> wrote:

I was under the impression that the `if let` syntax would check whether the condition was nil or not. But, when I run this code, if `sender.property` is nil, `selectedProperty` is nil and the if condition is executed branch is executed anyway.

I’m not 100% sure, but I think the problem is that you’re using “!” not “?”. While both of those result in storing the value as an optional, the “!” syntax makes it behave syntactically like a non-optional — that is, it will be dereferenced automatically. So I am guessing that “if let” with a “!” variable always succeeds, since with “!” you’re telling Swift “this can never be null”.

—Jens

PS: Also, I notice the snippet you posted is not legal Swift code, since it's accessing a property of  AnyObject, which has no properties defined. I assume you simplified it before posting?

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/FF23F2EF-411D-40C0-AA55-6F3382BF27EC%40mooseyard.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: "if let" syntax for legacy objective-c properties.

Brent Royal-Gordon
In reply to this post by Samuel Williams
This:

> - (void)resetSheet:(id)sender {
> if ([sender respondsToSelector:@selector(property)]) {
> PMProperty * selectedProperty = [sender performSelector:@selector(property)];
>
> if (selectedProperty) {
> self.tenure.property = (PMProperty *)[self.managedObjectContext objectWithID:selectedProperty.objectID];
> }
> }
> }

Has very different semantics from this:

> override func resetSheet(sender: AnyObject!) {
> if let selectedProperty = sender.property {
> self.propertyTransaction?.property = self.managedObjectContext.objectWithID(selectedProperty.objectID) as? PMProperty
> }
> }

The Objective-C code tests if sender has a property (really, a method) named “property”, and if it does, calls it and does something with the value if it’s not nil. The Swift code just calls “property”, *assuming* that sender is not nil and has a “property” property, and tests if the value is nil.

A direct translation of the Objective-C might look more like:

override func resetSheet(sender: AnyObject?) {
        if let selectedProperty = sender?.property? {
                self.propertyTransaction?.property = self.managedObjectContext.objectWithID(selectedProperty.objectID) as? PMProperty
        }
}

The question mark after “sender" indicates that “sender" might be nil, and the one after “property” indicates that “sender” might not have a “property” property. However, this doesn't actually compile in my playground—Swift doesn’t allow typing this loose.

You’re much better off giving “sender” a specific type:

override func resetSheet(sender: PMPropertyController?) {
        if let selectedProperty = sender?.property {
                self.propertyTransaction?.property = self.managedObjectContext.objectWithID(selectedProperty.objectID) as? PMProperty
        }
}

Or if you can’t guarantee the type of “sender” (or you can’t change the AnyObject in your superclass for some reason), use a type check:

override func resetSheet(sender: AnyObject?) {
        if let propertyController = sender as? PMPropertyController, selectedProperty = propertyController.property {
                self.propertyTransaction?.property = self.managedObjectContext.objectWithID(selectedProperty.objectID) as? PMProperty
        }
}

If “sender” can be one of several unrelated types, all of which have a “property” property, declare a PropertyHoldingType protocol that requires the “property” property and make all of the valid types conform to it. Then you can either make resetSheet(_:) take an instance of PropertyHoldingType, or do an “if let”/“as?” conditional cast to PropertyHoldingType.

HTH,
--
Brent Royal-Gordon
Architechies

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/DEF4E587-F95A-4CBA-885A-7552D6218A50%40architechies.com.
For more options, visit https://groups.google.com/d/optout.