在Swift中调用NSException.raise()

在Swift中调用NSException.raise(),swift,Swift,我试图通过调用NSException.raise()在Swift中引发异常。定义是: class func raise(_ name: String!, format format: String!, arguments argList: CVaListPointer) 但当我尝试以下方法时: NSException.raise("Exception", format:"Error: %@", arguments:getVaList([error])) 我得到编译错误:调用中的额外参数“fo

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

问题似乎是我没有将错误视为可选错误。以下工作:

var error: NSError?
NSException.raise("Exception", format:"Error: %@", arguments:getVaList([error!]))
或者,如果错误为零,您可以执行以下操作:

NSException.raise("Exception", format:"Error: %@", arguments:getVaList([error ?? "nil"]))
或:

或:


提问者发现,问题在于可选对象不符合
CVarArgType
,而非可选对象符合,因此您需要进行某种展开

如果我们看一下符合
CVarArgType
的类型,它们包括基本数字类型,
copaqueponinter
,并且
NSObject
具有使
NSObject
符合它的扩展名。不幸的是,这是一个直接的
NSObject
,而不是
NSObject?
,也不是我们想要的
AnyObject?
。因此,如果你有一个
NSObject?
,你可以用
打开它,但是如果它是
nil
,它就会崩溃。或者,如果您的对象不是
NSObject
的子类型,则也不能使用此对象

但是在C/Objective-C中,您可以将任何指针类型作为vararg传递,包括任何对象指针,并且无论它是否为空指针,它都可以工作。我们如何在Swift中复制这种行为

顺便说一句,他们不能使
AnyObject?
(即
可选
)符合
CVarArgType
,因为您不能为泛型类型的特定类型参数(如C++中的“模板专门化”)定义方法(无论是直接在类中还是在扩展中)。也许苹果将来会添加它。但是现在,
Optional
方法必须适用于所有类型参数。但我们不希望能够将非对象选项作为var args传递,所以这不起作用

但是,我们可以创建一个函数,将可选对象转换为
CVarArgType
。我们可以利用
NSObject
的一致性,处理它不处理的情况--
nil
nil
只是一个空指针,我们可以传递一个不同类型的空指针,一个
COpaquePointer
null指针,它可以工作,因为所有空指针在运行时都是相同的:

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)
}
func anyObjectToVarArg(obj:AnyObject?->CVarArgType{
返回(obj!=零)?
未托管。未保存的pass(对象!)。toOpaque():
(无作为COpaquePointer)
}

注意:Objective-C中不支持异常,但fr不可恢复编程错误除外。这会影响使用Objective-CAPI的Swift代码。这就是我使用它们的目的。如果出现致命错误,我希望应用程序停止运行,而不是继续处于半工作状态。越早知道错误越好。格式和参数仅用于构造字符串,该字符串作为“reason”参数传递给
init(名称:reason:userInfo:)
。使用
NSException(名称:reason:userInfo:)
创建异常要简单得多,传入一个以您自己的方式构造的原因字符串,然后对其调用
.raise()
错误!=无错误!:“nil”
可以写成
错误??“无”
。但更接近原始行为的是
error??(nil作为COpaquePointer)
感谢您指出@newacct,我已经更新了我的答案,加入了nil合并运算符。您将如何输出一个表达式,如:error??在插值字符串中的“nil”,即原因:“Error:(Error??“nil\”)@MarkHorgan在语句中创建字符串,并将其传递给
NSException
,作为原因。@zaph在第三个示例中,您应该删除
var e=
(我认为这只是一个复制粘贴错误)。
e
将被分配
raise()的返回值
,即
Void
NSException(name:"name", reason:"reason", userInfo:nil).raise()
import Foundation
func nsObjectToVarArg(obj: NSObject?) -> CVarArgType {
  return obj ?? (nil as COpaquePointer)
}
func anyObjectToVarArg(obj: AnyObject?) -> CVarArgType {
  return (obj != nil) ?
    Unmanaged<AnyObject>.passUnretained(obj!).toOpaque() :
    (nil as COpaquePointer)
}