在Swift中调用NSException.raise()

时间:2014-08-07 14:47:48

标签: swift

我试图通过调用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.

3 个答案:

答案 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的一致性,并处理它无法处理的案例 - nilnil只是一个空指针,我们可以传递一种不同类型的空指针,一个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)
}