Why can't we get `URL` equal on the same path?


(Zhao Xin) #1

As you can see, `URL` is not equal but the `path` is. I wonder why urls do
not equal here?

let url = URL(fileURLWithPath: "foo/bar", isDirectory: false)

let baseURL = url.deletingLastPathComponent()

let newURL = URL(fileURLWithPath: "bar", isDirectory: false, relativeTo:
baseURL)

print(url == newURL) // prints false

print(url.path == newURL.path) // prints true

Zhaoxin


(Greg Parker) #2

Here's one reason:
    print(url.baseURL == newURL.baseURL) // prints false

···

On Oct 14, 2016, at 7:33 AM, Zhao Xin via swift-users <swift-users@swift.org> wrote:

As you can see, `URL` is not equal but the `path` is. I wonder why urls do not equal here?

let url = URL(fileURLWithPath: "foo/bar", isDirectory: false)
let baseURL = url.deletingLastPathComponent()
let newURL = URL(fileURLWithPath: "bar", isDirectory: false, relativeTo: baseURL)

print(url == newURL) // prints false
print(url.path == newURL.path) // prints true

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler


(Zhao Xin) #3

In your opinion, `baseURL` is a factor more important than `path`. I can not unaccept your answer. But I want to know why? Is there a standard on URL equality?
ZhaoXin

···

Get Outlook for iOS

    _____________________________
From: Greg Parker <gparker@apple.com>
Sent: 星期六, 十月 15, 2016 05:40
Subject: Re: [swift-users] Why can't we get `URL` equal on the same path?
To: Zhao Xin <owenzx@gmail.com>
Cc: swift-users <swift-users@swift.org>

On Oct 14, 2016, at 7:33 AM, Zhao Xin via swift-users <swift-users@swift.org> wrote:
As you can see, `URL` is not equal but the `path` is. I wonder why urls do not equal here?
let url = URL(fileURLWithPath: "foo/bar", isDirectory: false)let baseURL = url.deletingLastPathComponent()let newURL = URL(fileURLWithPath: "bar", isDirectory: false, relativeTo: baseURL)
print(url == newURL) // prints falseprint(url.path == newURL.path) // prints true
Here's one reason: print(url.baseURL == newURL.baseURL) // prints false

-- Greg Parker gparker@apple.com Runtime Wrangler


(Jens Alfke) #4

I think this is just a weirdness of NSURL (assuming you’re running this code on macOS or iOS.) I’ve always avoided the `relativeTo:` initializers of NSURL because the objects they produce behave (IMHO) unexpectedly.

—Jens

···

On Oct 14, 2016, at 5:16 PM, zh ao via swift-users <swift-users@swift.org> wrote:

In your opinion, `baseURL` is a factor more important than `path`. I can not unaccept your answer. But I want to know why? Is there a standard on URL equality?


(Keith Smiley) #5

Just want to mention that there are some differences between `NSURL` and `URL`.
Here's an example from the repl:

  1> import Foundation
  2> NSURL(string: "")
$R0: NSURL? = "" {
  ObjectiveC.NSObject = {}
}
  3> URL(string: "")
$R1: URL? = nil
···

--
Keith Smiley

On 10/14, Jens Alfke via swift-users wrote:

> On Oct 14, 2016, at 5:16 PM, zh ao via swift-users <swift-users@swift.org> wrote:
>
> In your opinion, `baseURL` is a factor more important than `path`. I can not unaccept your answer. But I want to know why? Is there a standard on URL equality?

I think this is just a weirdness of NSURL (assuming you’re running this code on macOS or iOS.) I’ve always avoided the `relativeTo:` initializers of NSURL because the objects they produce behave (IMHO) unexpectedly.

—Jens

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


(Zhao Xin) #6

You are right Jens. If I use `appendingPathComponent`, it works.

let url = URL(fileURLWithPath: "foo/bar", isDirectory: false)

let baseURL = url.deletingLastPathComponent()

let newURL = URL(fileURLWithPath: "bar", isDirectory: false, relativeTo:
baseURL)

let testURL = baseURL.appendingPathComponent("bar")

print(url == newURL) // prints false

print(url.path == newURL.path) // prints true

print(url == testURL) // prints true

print(url.path == testURL.path) // prints true

Zhaoxin

···

On Sat, Oct 15, 2016 at 11:19 AM, Jens Alfke <jens@mooseyard.com> wrote:

> On Oct 14, 2016, at 5:16 PM, zh ao via swift-users < > swift-users@swift.org> wrote:
>
> In your opinion, `baseURL` is a factor more important than `path`. I can
not unaccept your answer. But I want to know why? Is there a standard on
URL equality?

I think this is just a weirdness of NSURL (assuming you’re running this
code on macOS or iOS.) I’ve always avoided the `relativeTo:` initializers
of NSURL because the objects they produce behave (IMHO) unexpectedly.

—Jens


(Keith Smiley) #7

FWIW we've overridden URL's equality function in order to get a "more realistic"
result. We lowercase everything and compare the scheme, host, port, and query,
along with normalizing the path to handle cases where `/` exists in some paths
but doesn't in others. This solves this problem as well:

  1> import Foundation
  2> let a = URL(string: "apple.com")
  3> let b = URL(string: "apple.com/")
b: URL? = "apple.com/"
  4> a == b
$R0: Bool = false

Note that if you do this, you have to define the `==` operator for URL in an
extension in the same module you plan to use it, otherwise you end up with some
unresolvable ambiguity.

···

a: URL? = "apple.com"

--
Keith Smiley

On 10/15, Zhao Xin via swift-users wrote:

You are right Jens. If I use `appendingPathComponent`, it works.

let url = URL(fileURLWithPath: "foo/bar", isDirectory: false)

let baseURL = url.deletingLastPathComponent()

let newURL = URL(fileURLWithPath: "bar", isDirectory: false, relativeTo:
baseURL)

let testURL = baseURL.appendingPathComponent("bar")

print(url == newURL) // prints false

print(url.path == newURL.path) // prints true

print(url == testURL) // prints true

print(url.path == testURL.path) // prints true

Zhaoxin

On Sat, Oct 15, 2016 at 11:19 AM, Jens Alfke <jens@mooseyard.com> wrote:

>
> > On Oct 14, 2016, at 5:16 PM, zh ao via swift-users < > > swift-users@swift.org> wrote:
> >
> > In your opinion, `baseURL` is a factor more important than `path`. I can
> not unaccept your answer. But I want to know why? Is there a standard on
> URL equality?
>
> I think this is just a weirdness of NSURL (assuming you’re running this
> code on macOS or iOS.) I’ve always avoided the `relativeTo:` initializers
> of NSURL because the objects they produce behave (IMHO) unexpectedly.
>
> —Jens
>
>

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


(Jens Alfke) #8

FWIW we've overridden URL's equality function in order to get a "more realistic"
result. We lowercase everything and compare the scheme, host, port, and query,

I hope you don’t lowercase everything — the scheme and host are case-insensitive, but the rest isn’t.

along with normalizing the path to handle cases where `/` exists in some paths
but doesn't in others.

In your example it’s true that “apple.com <http://apple.com/>” and “apple.com/ <http://apple.com/>“ are equivalent, but in general I don’t think a URL with a trailing “/“ is equivalent to one without. (For one thing, the behavior of applying a relative URL is different.)

—Jens

···

On Oct 14, 2016, at 10:20 PM, Keith Smiley <k@keith.so> wrote:


(Keith Smiley) #9

In our case, if we accidentally send a URL from the server with a trailing
slash, we want that to be equivalent to one without. But yea, if you're
manipulating it you might have more problems! Although in our case we add the
slash for the case without it.

···

--
Keith Smiley

On 10/14, Jens Alfke wrote:

> On Oct 14, 2016, at 10:20 PM, Keith Smiley <k@keith.so> wrote:
>
> FWIW we've overridden URL's equality function in order to get a "more realistic"
> result. We lowercase everything and compare the scheme, host, port, and query,

I hope you don’t lowercase everything — the scheme and host are case-insensitive, but the rest isn’t.

> along with normalizing the path to handle cases where `/` exists in some paths
> but doesn't in others.

In your example it’s true that “apple.com <http://apple.com/>” and “apple.com/ <http://apple.com/>“ are equivalent, but in general I don’t think a URL with a trailing “/“ is equivalent to one without. (For one thing, the behavior of applying a relative URL is different.)

—Jens