On 23 Feb 2015, at 8:18 AM, Juanjo Conti <jjco...@carouselapps.com> wrote:
> 
> I'm translating some code from Objective-C to Swift and in the middle of
> that, i found this problem.
> 
> theUrl is an instance of NSURL
> 
> theUrl.host?.lowercaseString
> 
> compiles ok.
> 
> But
> 
> NSString(string: theUrl.host?.lowercaseString)
> don't. It says "Value of optional type 'String?' no unwrapped; did you mean
> to use '!' or '?'?
> 
> If I click to add the fix, then it complains again and suggest to delete
> the '!' :)

This is written in haste, and few people are experts…

    theURL.host  may yield nil (host is declared String!, implicitly unwrapped, 
but optional).

    theURL.host?.lowercaseString  will short-circuit and be evaluated as nil if 
.host is nil.

    anyString.lowercaseString   may also yield nil; the var is declared String!.

    anyString.lowercaseString!   attempts to unwrap a String that the compiler 
has implicitly unwrapped already.

Therefore, because of the short-circuit “?”, the expression 
theUrl.host?.lowercaseString is of type String?, which may be .None (nil), or 
.Some(String) (and therefore have to be unwrapped).

You are passing that optional String as the argument for String(string: {that 
optional expression}). The argument may be nil; or it may need unwrapping. The 
initializer _requires_ a non-nil argument. It’s a righteous error.

The expression

        NSString(string: foo!)

is different; by adding the bang you’ve taken responsibility for the 
parameter’s not being nil.

Because .lowercaseString returns an implicitly-unwrapped String (String!),

    theURL?.host?.lowercaseString!

tries to unwrap something that is already, syntactically, an unwrapped String.

Quincey — my instinct is that the conditional-unwrap chain necessarily forces 
left-to-right evaluation, tighter than the . operator. The ! would mean, “if 
you got this far without short-circuiting, and b returns an optional, then 
unwrap it.” 

As of today’s Swift 1.2b2, the following in a playground:

    let aURL = NSURL(string: "http://wt9t.com/";)!
    NSString(string: aURL.host?.lowercaseString)

complains as you suggest: .host? is potentially nil — that would force the 
whole expression to be nil, and thus forbidden as a parameter. lowercaseString 
still gets treated as implicitly unwrapped — so a bang at the end of the whole 
expression is an attempt to unwrap something the compiler was going to unwrap 
anyway.




By the way: The use of +[NSString stringWithString:] or -[NSString 
initWithString:] is a code smell. The result of lowercaseString is declared as 
immutable, and you aren’t trying to initialize an NSMutableString with it. 
Foundation (unless I’m missing something) is free to treat it just as it does 
with -[NSString copy], and simply return the same object with the retain count 
bumped. Once you get into mutability, the smell goes away, and someone will 
surely jump in now with an explanation for why it’s needed more often than I 
think.


        — F



_______________________________________________

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

Reply via email to