UIImage(named:)和UIImage(imageLiteralResourceName:)有什么区别?

14

Swift 3/iOS 10 给 UIImage 添加了一个新的初始化器,名称为 imageLiteralResourceName

extension UIImage {

    required public convenience init(imageLiteralResourceName name: String)
}
这与“public init?(named name: String)”有什么不同?我知道“named”是可失败的初始化程序,而“imageLiteralResourceName”会在无效的图像名称上崩溃。 “imageLiteralResourceName”是否为性能而牺牲了安全性?您应该何时使用“imageLiteralResourceName”替代“named”?

1
苹果文档在这个主题上似乎不完整。链接 - Fonix
我还没有下载 Xcode 8,但我的猜测是 imageLiteralResourceName 只是新图像字面量的语法糖(而且你永远不会显式地调用它)。 - Martin R
@Fonix 看起来没有区别,参见 UIKit.swift - JAL
@MartinR在开源版本的Swift中找到了实现方式,看起来没有什么区别。如果只是为了新的图像字面量,苹果为什么不保持私有呢? - JAL
1
所有的 XxxLiteralConvertible 协议和相应的 init(xxxLiteral ...) 方法都是公共的,但我从未见过有理由显式地使用它们。 - Martin R
1个回答

11

查看UIKit的开源实现,似乎没有任何区别:

extension UIImage : _ImageLiteralConvertible {
  private convenience init!(failableImageLiteral name: String) {
    self.init(named: name)
  }

  public required convenience init(imageLiteralResourceName name: String) {
    self.init(failableImageLiteral: name)
  }
}

public typealias _ImageLiteralType = UIImage

它所做的就是强制解包init(named:)方法的结果。

看起来它只是实现了在CompilerProtocols.swift中找到的_ImageLiteralConvertible协议:

public protocol _ImageLiteralConvertible {
  init(imageLiteralResourceName path: String)
}

AppKit 也有类似的实现:

extension NSImage : _ImageLiteralConvertible {
  private convenience init!(failableImageLiteral name: String) {
    self.init(named: name)
  }

  public required convenience init(imageLiteralResourceName name: String) {
    self.init(failableImageLiteral: name)
  }
}

public typealias _ImageLiteralType = NSImage

这可能与Xcode 8新增的图像文本功能(#imageLiteral)有关,不应直接调用该功能。


参考资料1(开源UIKit存储库)的链接已过期。他们撤销了源代码还是移动了它?我在stdlib中找到了这个,但它并不是完整的实现。 - garritfra
我认为最后一句话可能是正确的。 - Marcy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接