首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将NSImage类型转换为Any,然后将其降回NSImage

将NSImage类型转换为Any,然后将其降回NSImage
EN

Stack Overflow用户
提问于 2015-03-07 19:20:16
回答 2查看 280关注 0票数 0

我想弄明白为什么

代码语言:javascript
复制
var tmp: Any = NSImage(byReferencingFile: somePath)
var img: NSImage = tmp as NSImage

将无法工作并导致错误,但是

代码语言:javascript
复制
var tmp: Any = NSImage(byReferencingFile: somePath) as Any!
var img: NSImage = tmp as NSImage

会做这份工作吗?有什么不同吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-07 20:17:37

这能将许多不同的问题打包成一小部分代码:-)这个解释很长,所以你可能会发现你知道它的第一部分,但最好从一开始就开始.

NSImage(byReferencingFile)就是所谓的“可失败初始化器”--即返回NSImage?的初始化器--一个可能包含或不包含NSImage对象的可选选项。

原因是,从该文件创建NSImage可能会失败(假设找不到该文件)。由于这个原因,它返回一个必须检查和打开的可选选项:

代码语言:javascript
复制
if let img = NSImage(byReferencingFile: somePath) {
    // img will be a valid NSImage
}
else {
    // img was not valid, handle error here if you want
}

现在,如果您尝试将一个NSImage? (如可故障初始化器返回的)分配给一个非可选的NSImage,您将得到一个错误,因为您不能这样做--您需要执行上面所示的解包装操作:

代码语言:javascript
复制
// error: value of optional type 'NSImage?' not unwrapped; did you mean to use '!' or '?'?
let img: NSImage = NSImage(byReferencingFile: somePath)

处理此问题的一种方法,如上面的错误消息所述,而不是用if … let展开图像,而是“强制-展开”可选选项,如下所示:

代码语言:javascript
复制
let img: NSImage = NSImage(byReferencingFile: somePath)!
                             // note exclamation mark -^

这个!的意思是:不用费心检查零,只要假设结果是有效的,然后打开它。这有时是个好主意,但通常是个非常糟糕的主意。如果您曾经强制展开一个零值,您的程序将突然退出错误。因此,除非您100%确定该值不可能为零(这不是很常见),否则您应该避免这样做。

那么Any!是如何影响这一切的呢?

后面带有!的类型是“隐式未包装的可选”。这些都是选项,但你不必手动强制展开。你可以像普通值一样访问它们--但是,如果你曾经访问过一个零值,你的应用程序就会退出。

这样您就可以写以下内容:

代码语言:javascript
复制
let img: NSImage! = NSImage(byReferencingFile: somePath)
// or, this is basically the same thing:
let img = NSImage(byReferencingFile: somePath) as NSImage!

现在,您可以将img当作不是可选的了。但是,如果像以前一样是零,它就会崩溃。区别在于,当您使用img时,它将崩溃,而不是当您将它分配给img时。

最后,Any是一种可以容纳任何类型的类型,但是如果不返回真正的类型,那么它是非常无用的。您通常应该用as?来完成这个任务。as?检查Any是否包含该类型,并返回包含该值的可选选项,如果包含其他类型,则返回零。

如果您将一个可选项放入一个Any中,然后尝试将其解压为非可选类型,则它将失败并返回零,因为您输入的类型与尝试退出的类型不相同。

如果您使用没有问号的as,这会强制提取而不将其包装在可选的范围内,并且,您猜到了,如果错误的话,它将在运行时崩溃。事实上,这看起来很危险,在新的1.2测试版的Swift中,它已经被as!所取代,以匹配它的强制展开特性。在第一个示例中,您输入了一个NSImage?,您提取了一个非可选的NSImage,并使用了as,因此您得到了一个运行时断言。

总之,Any!将上述所有功能结合到一个令人愉快的春季死亡陷阱中.它将愉快地采取一种可选类型,然后允许您将其内容提取为非可选类型,而无需检查。这就是在您的代码中发生的事情--您正在将一个可选的内容放入一个Any!中,然后将其作为一个非可选的。这几乎肯定是个坏主意,因为如果找不到您的图像文件,它就会崩溃,所以您最好在这个答案一开始就使用代码从图像中提取值。

票数 1
EN

Stack Overflow用户

发布于 2015-03-07 19:54:49

因为NSImage(byReferencingFile: somePath)返回一个可选的。如果您查看文档,您可以看到签名是:

init?(byReferencingFile filename: String)

init后面的问号意味着初始化程序可能失败,并且返回一个可选的值。因此,例如,当文件不存在时,它将返回nil而不是NSImage实例。

你可以通过这样做来fix .

代码语言:javascript
复制
var tmp: Any = NSImage(byReferencingFile: somePath)
var img: NSImage? = tmp as? NSImage

..。不过,这并不是一个真正的解决办法。

第二个示例之所以有效,是因为您强制使用Any!展开可选选项。你基本上是说,忽略可选的值是什么,只要给我它包装的图像。但是,如果无法加载图像,这将崩溃。

理想情况下,您想要做的是:

代码语言:javascript
复制
if let image = NSImage(byReferencingFile: somePath) {
    // Here the "if let" has checked and unwrapped the optional
    // and you can be sure that image is not nil.
}

这有用吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28918937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档