我试图通过调用NSException.raise()在Swift中引发异常。定义是:
class func raise(_ name: String!, format format: String!, arguments argList: CVaListPointer)
但是当我尝试以下内容时:
NSException.raise("Exception", format:"Error: %@", arguments:getVaList([error]))
我得到编译错误:调用中的额外参数'format'。
任何想法我做错了什么?我正在使用XCode 6 Beta 5.
答案 0 :(得分:19)
问题似乎是我没有将错误视为可选项。以下作品:
var error: NSError?
NSException.raise("Exception", format:"Error: %@", arguments:getVaList([error!]))
或者如果错误为零,您可以执行以下操作:
NSException.raise("Exception", format:"Error: %@", arguments:getVaList([error ?? "nil"]))
答案 1 :(得分:16)
var e = NSException(name:"name", reason:"reason", userInfo:["key":"value"])
e.raise()
或者:
var e = NSException(name:"name", reason:"reason", userInfo:nil)
e.raise()
或者:
NSException(name:"name", reason:"reason", userInfo:nil).raise()
答案 2 :(得分:2)
正如提问者所发现的那样,问题是可选对象不符合CVarArgType
,而非可选对象也是如此,所以你需要进行某种展开。
如果我们查看符合CVarArgType
的类型,则它们包含原始数字类型COpaquePointer
,而NSObject
具有使NSObject
符合它的扩展名。不幸的是,这是我们可能想要的直接NSObject
,而不是NSObject?
,而不是AnyObject?
。因此,如果您有NSObject?
,则可以使用!
解包,但如果它nil
,它就会崩溃。或者,如果您的对象不是NSObject
的子类型,那么您也无法使用它。
但是在C / Objective-C中,你可以将任何指针类型作为vararg传递,包括任何对象指针,无论它是否为空指针都可以工作。我们如何在Swift中复制这种行为?
顺便说一句,他们无法使AnyObject?
(即Optional<AnyObject>
)符合CVarArgType
,因为您无法定义方法(无论是直接在课堂上,还是对于泛型类型的特定类型参数(例如&#34;模板特化&#34;在C ++中)。也许苹果将在未来添加它。但是现在Optional
的方法必须适用于所有类型的参数。但我们不希望能够将非对象选项作为var args传递,因此不起作用。
但是,我们可以创建一个将可选对象转换为CVarArgType
的函数。我们可以利用NSObject
的一致性,并处理它无法处理的案例 - nil
。 nil
只是一个空指针,我们可以传递一种不同类型的空指针,一个COpaquePointer
空指针,它将起作用,因为所有空指针在运行时都是相同的:
import Foundation
func nsObjectToVarArg(obj: NSObject?) -> CVarArgType {
return obj ?? (nil as COpaquePointer)
}
对于那些不是(或我们不知道)NSObject
的子类型的对象怎么办?我做了一个更粗略的版本:
func anyObjectToVarArg(obj: AnyObject?) -> CVarArgType {
return (obj != nil) ?
Unmanaged<AnyObject>.passUnretained(obj!).toOpaque() :
(nil as COpaquePointer)
}