Давайте рассмотрим его из исходного кода, поскольку Swift Foundation является открытым исходным кодом.
Инициализатор URLComponents реализован в apple/swift. – URLComponents.swift и apple/ swift-corelibs-foundation — URLComponents.swift и просто вызывает инициализатор NSURLComponents.
Инициализатор NSURLComponents реализован в apple/swift-corelibs. -foundation – NSURL.swift и просто вызывает _CFURLComponentsCreateWithURL.
_CFURLComponentsCreateWithURL реализован в apple/swift -corelibs-foundation – CFURLComponents.c и выполняет:
- a failable copy with
CFURLCopyAbsoluteURL
- a failable creation with
_CFURLComponentsCreateWithString which calls:
_CFURIParserParseURIReference + a failable _CFURIParserURLStringIsValid
CFURLCopyAbsoluteURL реализован в apple/swift -corelibs-foundation – CFURL.c и не работает только для:
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( base && CFURLIsFileReferenceURL(base) && !CFURLHasDirectoryPath(base) ) {
// 16695827 - If the base URL is a file reference URL which doesn't end with a slash, we have to convert it to a file path URL before we can make it absolute.
base = CFURLCreateFilePathURL(alloc, base, NULL);
if ( !base ) {
// could not convert file reference URL to file path URL -- fail will NULL
return NULL;
}
}
#endif
Реализация CFURLCreateFilePathURL находится в opensource.apple.com/source /CF — CFURL.c, и, насколько я понимаю, он завершится ошибкой только в том случае, если нет схемы или пути, что невозможно, поскольку мы ранее проверяли файловую схему или существование файла с помощью CFURLIsFileReferenceURL.
_CFURIParserParseURIReference реализован в apple/swift -corelibs-foundation — CFURLComponents_URIParser.c и завершится ошибкой только в том случае, если длина URL-адреса превышает 2 ГБ, что, как мне кажется, не связано со спецификациями RFC.
_CFURIParserURLStringIsValid будет по существу вызовите _CFURIParserValidateComponent для каждого компонента и сбой для недопустимых символов или escape-последовательностей. Возможно, это самая важная часть.
Теперь, немного поэкспериментировав, мы знаем, что нам нужна схема (например, https:// или просто a://), и мы играем с зарезервированными символами, чтобы получить такие примеры, как:
// OK
let url = URL(string: "a://@@")!
// CRASH
let components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
Попытка использовать альтернативный инициализатор URLComponents также не увенчается успехом, поэтому не пытайтесь думать, что он другой:
// CRASH
let components = URLComponents(string: url.absoluteString)!
Вывод
"a://@@" является примером действительного NSURL, но недопустимого RFC 3986.
Кстати, некоторые пользователи Swift, кажется, желают в будущем унифицировать поддержку URL и URLComponents (больше никаких различий RFC) /public/Darwin/Foundation/URL.swift#L641" rel="noreferrer">как показано в URL.swift:
// Замечание о будущей реализации:
// NSURL (на самом деле CFURL, который обеспечивает его реализацию) имеет довольно много причуд при обработке некоторых более эзотерических (и некоторых не очень) строк. Мы хотели бы перенести большую часть этого на более современные NSURLComponents, но из-за проблем с совместимостью двоичных файлов это затруднилось.
// Надеемся, что вскоре мы сможем заменить некоторые из приведенных ниже делегаций в NSURL делегированием в NSURLComponents. Это нельзя делать по частям, потому что иначе мы получим противоречивые результаты от API.
Я не уверен, как они планируют это сделать, так как это означало бы, что либо URL(string: "a://@@") потерпит неудачу, либо URLComponents(string: "a://@@") преуспеет.
person
Cœur
schedule
11.04.2019