NSURL 扩展采用 StringLiteralConvertible
NSURL extension to adopt StringLiteralConvertible
根据来自 NSHipster 的 post,我们扩展了 NSURL
class 以使用如下文字初始化 NSURL
对象:
// the following is a full fledged NSURL object
let url: NSURL = "http://nshipster.com/"
不幸的是,post 是在 Swift 首次公布时编写的,它不再编译。
我能够让自己的自定义对象符合 StringLiteralConvertible
,它看起来像这样:
final class Dog {
let name: String
init(name: String) {
self.name = name
}
}
// MARK: - StringLiteralConvertible
extension Dog: StringLiteralConvertible {
typealias UnicodeScalarLiteralType = StringLiteralType
typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
convenience init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.init(stringLiteral: value)
}
convenience init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.init(stringLiteral: value)
}
convenience init(stringLiteral value: StringLiteralType) {
self.init(name: value)
}
}
效果很好。例如,以下两行代码将创建一个 Dog
对象:
let dog = Dog(name: "Bob")
let dog: Dog = "Bob"
不幸的是,通过扩展 NSURL
使用此策略遇到了错误:
extension NSURL: StringLiteralConvertible {
public typealias UnicodeScalarLiteralType = StringLiteralType
public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
convenience public init?(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.init(stringLiteral: value)
}
convenience public init?(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.init(stringLiteral: value)
}
convenience public init?(stringLiteral value: StringLiteralType) {
self.init(string: value)
}
}
我一直在研究编译器错误,一次解决 1 个猜测。但是,我无法克服每个初始化程序发生的以下错误:
Initializer requirement 'init(...)' can only be satisfied by a 'required' initializer in the definition of non-final class 'NSURL'
添加 required
关键字会导致您可能未在扩展中声明必需的初始值设定项。
正在寻找方向:|
StringLiteralConvertible 支持
不幸的是,StringLiteralConvertible
在当前的 Swift 版本 (2.2) 中似乎无法支持 NSURL
。我能得到的最接近的是:
extension NSURL: StringLiteralConvertible {
public convenience init(stringLiteral value: String) {
self.init(string: value)!
}
public convenience init(extendedGraphemeClusterLiteral value: String) {
self.init(string: value)!
}
public convenience init(unicodeScalarLiteral value: String) {
self.init(string: value)!
}
}
但是编译器抱怨:
Playground execution failed: OS X Playground.playground:5:24: error: initializer requirement 'init(stringLiteral:)' can only be satisfied by a `required` initializer in the definition of non-final class 'NSURL'
public convenience init(stringLiteral value: String) {
^
OS X Playground.playground:3:24: error: initializer requirement 'init(extendedGraphemeClusterLiteral:)' can only be satisfied by a `required` initializer in the definition of non-final class 'NSURL'
public convenience init(extendedGraphemeClusterLiteral value: String) {
^
OS X Playground.playground:7:24: error: initializer requirement 'init(unicodeScalarLiteral:)' can only be satisfied by a `required` initializer in the definition of non-final class 'NSURL'
public convenience init(unicodeScalarLiteral value: String) {
并且 required
初始化器不能在扩展中实现。
备选方案
我们可以从另一端简化字符串到URL的转换!
extension String {
var url: NSURL? {
return NSURL(string: self)
}
}
var url = "http://google.coom/".url
print(url?.scheme) // Optional("http")
另一种选择是子类化 NSURL
并符合那里的 StringLiteralConvertible
。
class URL: NSURL, StringLiteralConvertible {
<#...#>
}
根据来自 NSHipster 的 post,我们扩展了 NSURL
class 以使用如下文字初始化 NSURL
对象:
// the following is a full fledged NSURL object
let url: NSURL = "http://nshipster.com/"
不幸的是,post 是在 Swift 首次公布时编写的,它不再编译。
我能够让自己的自定义对象符合 StringLiteralConvertible
,它看起来像这样:
final class Dog {
let name: String
init(name: String) {
self.name = name
}
}
// MARK: - StringLiteralConvertible
extension Dog: StringLiteralConvertible {
typealias UnicodeScalarLiteralType = StringLiteralType
typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
convenience init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.init(stringLiteral: value)
}
convenience init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.init(stringLiteral: value)
}
convenience init(stringLiteral value: StringLiteralType) {
self.init(name: value)
}
}
效果很好。例如,以下两行代码将创建一个 Dog
对象:
let dog = Dog(name: "Bob")
let dog: Dog = "Bob"
不幸的是,通过扩展 NSURL
使用此策略遇到了错误:
extension NSURL: StringLiteralConvertible {
public typealias UnicodeScalarLiteralType = StringLiteralType
public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
convenience public init?(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.init(stringLiteral: value)
}
convenience public init?(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.init(stringLiteral: value)
}
convenience public init?(stringLiteral value: StringLiteralType) {
self.init(string: value)
}
}
我一直在研究编译器错误,一次解决 1 个猜测。但是,我无法克服每个初始化程序发生的以下错误:
Initializer requirement 'init(...)' can only be satisfied by a 'required' initializer in the definition of non-final class 'NSURL'
添加 required
关键字会导致您可能未在扩展中声明必需的初始值设定项。
正在寻找方向:|
StringLiteralConvertible 支持
不幸的是,StringLiteralConvertible
在当前的 Swift 版本 (2.2) 中似乎无法支持 NSURL
。我能得到的最接近的是:
extension NSURL: StringLiteralConvertible {
public convenience init(stringLiteral value: String) {
self.init(string: value)!
}
public convenience init(extendedGraphemeClusterLiteral value: String) {
self.init(string: value)!
}
public convenience init(unicodeScalarLiteral value: String) {
self.init(string: value)!
}
}
但是编译器抱怨:
Playground execution failed: OS X Playground.playground:5:24: error: initializer requirement 'init(stringLiteral:)' can only be satisfied by a `required` initializer in the definition of non-final class 'NSURL'
public convenience init(stringLiteral value: String) {
^
OS X Playground.playground:3:24: error: initializer requirement 'init(extendedGraphemeClusterLiteral:)' can only be satisfied by a `required` initializer in the definition of non-final class 'NSURL'
public convenience init(extendedGraphemeClusterLiteral value: String) {
^
OS X Playground.playground:7:24: error: initializer requirement 'init(unicodeScalarLiteral:)' can only be satisfied by a `required` initializer in the definition of non-final class 'NSURL'
public convenience init(unicodeScalarLiteral value: String) {
并且 required
初始化器不能在扩展中实现。
备选方案
我们可以从另一端简化字符串到URL的转换!
extension String {
var url: NSURL? {
return NSURL(string: self)
}
}
var url = "http://google.coom/".url
print(url?.scheme) // Optional("http")
另一种选择是子类化 NSURL
并符合那里的 StringLiteralConvertible
。
class URL: NSURL, StringLiteralConvertible {
<#...#>
}