URLComponents.init(url:resolvingAgainstBaseURL:)
的文档说:
返回初始化的URL组件对象;如果无法解析URL,则返回nil。
知道:
我假设URL符合RFC 1808/1738/2732但不符合RFC 3986时,URLComponents
的初始化将失败。那是什么类型的URL?有什么例子吗?
我到目前为止唯一的暗示可能与不同的保留字符有关?
答案 0 :(得分:2)
由于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 GB时才会失败,我认为这与RFC规范无关。
_CFURIParserURLStringIsValid
实际上将为每个组件调用_CFURIParserValidateComponent
,并且对于无效字符或转义序列将失败。 这可能是最相关的部分。
现在,通过一些实验,我们知道我们需要一个方案(例如https://
或简单的a://
),并且我们使用保留字符来举例,例如: / p>
// 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差异)as seen in URL.swift:
//将来的实现说明:
// NSURL(实际上是CFURL,提供其实现)在处理一些更深奥的(有些不是那么深奥的)字符串时有很多怪癖。我们想将其中的大部分转移到更现代的NSURLComponents上,但是二进制兼容性问题使这变得很困难。
//希望很快,我们可以将以下某些对NSURL的委托替换为对NSURLComponents的委托。不能零星地完成它,因为否则我们将从API中获得不一致的结果。
我不确定他们计划如何执行此操作,因为这将意味着URL(string: "a://@@")
将失败或URLComponents(string: "a://@@")
将成功。