> On Mar 10, 2015, at 21:17, Roland King <r...@rols.org> wrote:
> 
> 
>> On 11 Mar 2015, at 00:24, Bill Cheeseman <wjcheese...@gmail.com> wrote:
>> 
>> I'm using Xcode 6.2 and Swift 1.1.
>> 
>> 1. The following statement reports the error "'NSURL?' does not have a 
>> member named 'path'" even though executableURL has a trailing exclamation 
>> point to unwrap it. The caret identifying the location of the error is 
>> placed under the exclamation point.
>> 
>> for thisApp in NSWorkspace.sharedWorkspace().runningApplications {
>>    let thisPath = thisApp.executableURL!.path // ERROR
>> }
>> 
>> If I change executableURL to bundleURL, the error goes away. Yet 
>> executableURL and bundleURL are declared identically according to the 
>> NSRunningApplication reference document. As far as I know, bundleURL and 
>> executableURL both satisfy fileURL.
>> 
>> The error also goes away if I assign thisApp to a local variable and 
>> expressly downcast it to NSRunningApplication, as shown below. Why would I 
>> need to do that with executableURL, when it isn't necessary with bundleURL?
>> 
>> for thisApp in NSWorkspace.sharedWorkspace().runningApplications {
>>    let myAppAndIMeanIt = thisApp as NSRunningApplication
>>    let thisPath = myAppAndIMeanIt.executableURL!.path // NO ERROR
>> }
>> 
>> Is this a Swift bug?
>> 
> 
> No, one of yours again - although I don't really understand what's going on 
> with the plethora of optionals it's pretty easy, using something I've 
> recommended dozens of times, to gain insight into what the compiler thinks 
> it's doing by, as usual, splitting the line up into two assignments and using 
> opt option+click to see what type it has guessed things are. 
> 
> In the first case if you split out thisApp.executableURL into its own line 
> you will find it's of type 'NSURL?!'. I actually don't know entirely what 
> that means, an implicitly unwrapped optional to an optional. I suppose it's 
> means it's possibly something which is possibly an NSURL with an implicit 
> guarantee that it's not nothing at all. 

.executableURL has type NSURL? in all Cocoa classes that provide it (NSBundle & 
NSRunningApplication), so that’s one optionality level.

Note that `thisApp` has type AnyObject because 
NSWorkspace.runningApplications() returns [AnyObject]. But 
thisApp.executableURL forces Swift to downcast `thisApp` to some type that 
provides .executableURL, and this downcast might succeed or not — there’s the 
other optionality level.

> Anyway your '!' before '.path' just unwraps the implicitly unwrapped optional 
> bit. Yes I know it's implicitly unwrapped already but I believe the '!' just 
> unwraps it from implicitly unwrapped optional to optional NSURL to really 
> unwrapped, ie optional NSURL. So you need two '!!', one for the '!' and one 
> for the '?'. 
> 
> let thisPath = thisApp.executableURL!!.path
> 
> I tried to move the ugliness around a bit, you can do 
> 
> for thisApp in NSWorkspace.sharedWorkspace().runningApplications as [ 
> NSRunningAppliction ]
> {
>       let thisPath = thisApp.executableURL!.path
> }
> 
> except in 6.3 now you can't do that, you have to have 'as!', so it isn't much 
> nicer although possibly more consistent
> 
> 
> Why does this happen with executableURL and not bundleURL, I don't really 
> know. Both those properties are defined on both NSBundle and 
> NSRunningApplication however the bundleURL is non-optional on both of them 
> and the executableURL is optional on NSRunningApplication but not on 
> NSBundle. Since runningApplications returns an [ AnyObject ] I assume there's 
> one level of optionality in err ... something and then another one in 
> executableURL because it might be optional, or not. 

Much like in Objective-C. If you write

void someFunction(id obj) {
    NSLog(@"%@", [obj bundleURL]);
}

the compiler picks *some* method that matches that selector—which method is 
undefined. This can be problematic when multiple methods have the same selector 
but different types; in particular, when one method has a floating-point type 
in its signature and another method doesn’t.

In Objective-C, -bundleURL isn’t a problem. In Swift, it can be a problem 
because NSBundle.bundleURL has type NSURL (not an optional) whereas 
NSRunningApplication.bundleURL has type NSURL? (an optional). In Bill’s case, 
the compiler is choosing NSBundle.bundleURL. Which method/property is chosen is 
probably undefined in Swift as well.

> 
> Amusing crash of the day whilst trying to work this out
> 
> import Cocoa
> 
> for thisApp in NSWorkspace.sharedWorkspace().runningApplications  
> {
>       //let pp = thisApp as! NSRunningApplication
>       let tt = thisApp.bundleURL!.path
> }
> 
> works fine. However if you uncomment the commented line, which does nothing 
> but set an unused variable, the line below crashes with EXC_i386_INVOP. 
> That's 6.3, in 6.2 you have to remove the '!' in the commented line after the 
> 'as', however you still get the same crash. 
> 
> All this to work around nil, a concept I've always rather liked. 


_______________________________________________

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