NSURL扩展采用StringLiteralConvertible

时间:2016-04-25 07:55:12

标签: ios iphone swift nsurl

根据NSHipster的这个post,我们已经使用这样的文字扩展了NSURL类来初始化NSURL个对象:

// the following is a full fledged NSURL object
let url: NSURL = "http://nshipster.com/"

不幸的是,这篇文章是在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)
  }
}

我一直在编译错误,一次解决它们。但是,我无法通过每个初始化程序发生以下错误:

Initializer requirement 'init(...)' can only be satisfied by a 'required' initializer in the definition of non-final class 'NSURL'

添加required关键字会给出错误,即您可能未在扩展程序中声明所需的初始值设定项。

寻找一些方向:|

2 个答案:

答案 0 :(得分:1)

StringLiteralConvertible支持

不幸的是,StringLiteralConvertibleNSURL的支持似乎在当前的Swift版本(2.2)中是不可能的。我能得到的最接近的是:

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初始化程序无法在扩展程序中实现。

替代解决方案

我们可以从另一方面简化字符串到网址的转换!

extension String {

    var url: NSURL? {
        return NSURL(string: self)
    }

}

var url = "http://google.coom/".url
print(url?.scheme) // Optional("http")

答案 1 :(得分:0)

另一种选择是继承NSURL并在那里符合StringLiteralConvertible

class URL: NSURL, StringLiteralConvertible {

    <#...#>
}