Thanks Rod, very enlightening!

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl




> On 06 Jan 2017, at 15:19, Rod Brown <rodney.bro...@icloud.com> wrote:
> 
> 
>> On 7 Jan 2017, at 12:50 am, Rien <r...@balancingrock.nl> wrote:
>> 
>> Hmm, that is interesting to know. I had not realised that URL is in fact NOT 
>> a NSURL but a new type that is based on NSURL (and can be toll-free bridged 
>> I assume?).
> 
> URL a new Type, which internally wraps a NSURL reference. It is practically 
> toll free bridged, as URL is simply a struct wrapper placed around the 
> internal reference.
> 
> NSURL is a class and has reference semantics. That is, if you change the URL, 
> it would change all URLs with the same reference. This is why NSURL doesn’t 
> allow mutation. If you look at the NSURL API, it has a lot of methods like 
> “URLByAppendingPathComponent” which import into Swift 3 as 
> “appendingPathComponent()”. These return *copies* of the NSURL reference, 
> with the applied mutation.
> 
> URL is a struct and has value semantics. That is, if you change the URL, it 
> only changes the struct at this place and has no wider effects. Thus, there 
> are new mutating methods on this struct, love “appendPathExtension()” and 
> “appendPathComponent()” that allow mutation, because it only affects this 
> local copy. These methods internally actually use the 
> appendingPathComponent() method to get a replacement NSURL instance internal 
> of the struct.
> 
> The URL struct mutating behaviour makes URL manipulation much more convenient 
> in Swift 3.
> 
>> I also presume that the same is true for Data/NSData, Date/NSDate etc?
> 
> Correct. Except Date/NSDate is actually a slight edge case.
> 
> Instead of Date simply wrapping an NSDate, it actually only wraps the 
> NSDate’s timeIntervalSinceReferenceDate. This is because there’s no point 
> wrapping the internal reference to the NSDate, it’s more performant simply to 
> wrap the NSTimeInterval (a Double) and get true struct properties. You should 
> note that this means when you cast from Date to NSDate, you need to create a 
> new reference each time.
> 
> This becomes a bigger issue for IndexPath/NSIndexPath which also does this. 
> Casting between NSIndexPath and IndexPath can be somewhat less performant, as 
> it can hold an arbitrarily large number of integers. It’s also interesting to 
> note that NSIndexPath has an optimisations that could make it perform better 
> than IndexPath: NSIndexPath uses tagged pointers for row/item and section 
> conveniences on iOS, and IndexPath does not. This should really not concern 
> you generally, but you should avoid casting backwards and forwards between 
> the Struct and Reference types a lot as this could cause unnecessary 
> performance problems.
> 
> If you want to see the struct overlay for Foundation for yourself, take a 
> look here:
> https://github.com/apple/swift/tree/master/stdlib/public/SDK/Foundation
> 
>> 
>> (Failure on my part, as I did of course know that the .path method/var is in 
>> fact different on URL and NSURL)
>> 
>> Regards,
>> Rien
>> 
>> Site: http://balancingrock.nl
>> Blog: http://swiftrien.blogspot.com
>> Github: http://github.com/Swiftrien
>> Project: http://swiftfire.nl
>> 
>> 
>> 
>> 
>>> On 06 Jan 2017, at 14:39, Rod Brown via swift-users <swift-users@swift.org> 
>>> wrote:
>>> 
>>> Hi Jan,
>>> 
>>> The Swift 3 URL struct has a modernized version of the NSURL API which 
>>> works far better in Swift. This replaces “getResourceValue(…)” with the API 
>>> you mentioned: “resourceValues(forKeys:)”.
>>> 
>>> 
>>> Previously, in Swift 2, you had to use an separate value, use 
>>> AutoreleasingUnsafeMutablePointers, conditionally cast and then hope you 
>>> got the value, and that you used the correct typecast for the key you were 
>>> asking for:
>>> 
>>> let url = NSURL(fileURLWithPath: "/Users/me/Desktop/File.png")
>>> 
>>> var fileType: AnyObject? = nil
>>> do {
>>>    try url.getResourceValue(&fileType, forKey: NSURLTypeIdentifierKey)
>>> 
>>>    if let type = fileType as? String {
>>>        // Use the file type here
>>>    } else {
>>>        // Handle error
>>>    }
>>> } catch {
>>>    // Handle error
>>> }
>>> 
>>> 
>>> In Swift 3 with the new Swift URL, the resourceValues(forKeys:) creates a 
>>> struct with optional type safe properties representing each resource key 
>>> type, and returns it, allowing you to use if let syntax:
>>> 
>>> let url = URL(fileURLWithPath: "/Users/me/Desktop/File.png")
>>> if let resourceValues = try? url.resourceValues(forKeys: 
>>> [.typeIdentifierKey]),
>>>   let fileType = resourceValues.typeIdentifier {
>>>       // Use the file type here
>>> }
>>> 
>>> 
>>> This is a much cleaner, clearer, and type-safe API.
>>> 
>>> If you want to use the old API, you can simply cast back to NSURL if you 
>>> require the old behaviour. That said, the new one should serve all your 
>>> needs and make things so much easier so I recommend you give it a go.
>>> 
>>> Hope this helps,
>>> 
>>> Rod
>>> 
>>> 
>>> 
>>> 
>>>> On 6 Jan 2017, at 6:36 am, J.E. Schotsman via swift-users 
>>>> <swift-users@swift.org> wrote:
>>>> 
>>>> Hello,
>>>> 
>>>> Is getResourceValue a method or URL or only on NSURL?
>>>> After migrating a project to Swift 3 I have code like
>>>> 
>>>> var file:URL
>>>> file.getResourceValue(...) // compiles!
>>>> 
>>>> From the documentation and the headers I get the impression that this 
>>>> should not compile!
>>>> 
>>>> TIA,
>>>> 
>>>> Jan E.
>>>> _______________________________________________
>>>> swift-users mailing list
>>>> swift-users@swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>> 
>>> _______________________________________________
>>> swift-users mailing list
>>> swift-users@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-users
>> 
> 

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

Reply via email to