Давайте рассмотрим его из его исходного кода, поскольку 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 и делает:
- ошибочную копию с
CFURLCopyAbsoluteURL
- неудачное создание с
_CFURLComponentsCreateWithString
, которая вызывает: _CFURIParserParseURIReference
+ неисправный _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) как видно в URL.swift :
// Примечание о будущей реализации:
// NSURL(на самом деле CFURL, который обеспечивает его реализацию) имеет довольно много особенностей при обработке некоторых более эзотерических (и некоторых не очень эзотерических) строк.Мы хотели бы перенести большую часть этого на более современные NSURLComponents, но проблемы двоичного компатации сделали это трудным.
// Надеемся, что скоро мы сможем заменить некоторые из нижеприведенного делегирования в NSURL делегированием вместо NSURLComponents.Это не может быть сделано по частям, потому что в противном случае мы получим противоречивые результаты от API.
Я не уверен, как они планируют это сделать, поскольку это будет означать, что либо URL(string: "a://@@")
потерпит неудачу, либоURLComponents(string: "a://@@")
будет успешным.