> On Mar 10, 2015, at 21:17, Roland King <[email protected]> wrote:
>
>
>> On 11 Mar 2015, at 00:24, Bill Cheeseman <[email protected]> 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 ([email protected])
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 [email protected]