很多时候,我将从框架中收到一个Swift Error
对象,它实际上是一个NSError
。
为了访问其信息(例如code
),我需要将其转换为NSError
:
(error as NSError).code == ....
为什么这只是无条件的as
?如果我设计自己的符合Error
的错误类,则不一定是NSError
,那么这怎么是执行此强制转换的正确方法呢?
类型系统中是否存在某种特殊情况?这是下流,其行为类似于上流。
答案 0 :(得分:7)
我相信Error
可转换为NSError
的功能已硬编码到编译器中,并且实际的桥接是在Swift运行时中实现的。
在https://www.ghandi.com.mx中,我发现了以下评论:
// This implements the object representation of the standard Error
// type, which represents recoverable errors in the language. This
// implementation is designed to interoperate efficiently with Cocoa libraries
// by:
// - ...
// - allowing a native Swift error to lazily "become" an NSError when
// passed into Cocoa, allowing for cheap Swift to Cocoa interop
/// Take an Error box and turn it into a valid NSError instance.
id
swift::_swift_stdlib_bridgeErrorToNSError(SwiftError *errorObject) {
...
// Otherwise, calculate the domain, code, and user info, and
// initialize the NSError.
auto value = SwiftError::getIndirectValue(&errorObject);
auto type = errorObject->getType();
auto witness = errorObject->getErrorConformance();
NSString *domain = getErrorDomainNSString(value, type, witness);
NSInteger code = getErrorCode(value, type, witness);
NSDictionary *userInfo = getErrorUserInfoNSDictionary(value, type, witness);
...
}
this function说出了基本原理:
通过使用合格的类型名称作为域键,枚举器作为错误代码并转换有效负载,应该有可能将符合
Error
的任意Swift枚举转换为NSError
进入用户数据。
(文档的某些部分可能已过时。)
ErrorHandling.rst document(我认为)类型检查器中至少有一部分是对Error
可转换为NSError
的信息进行了编码(可能还有更多):
// Check whether the type is an existential that contains
// Error. If so, it's bridged to NSError.
if (type->isExistentialWithError()) {
if (auto nsErrorDecl = getNSErrorDecl()) {
// The corresponding value type is Error.
if (bridgedValueType)
*bridgedValueType = getErrorDecl()->getDeclaredInterfaceType();
return nsErrorDecl->getDeclaredInterfaceType();
}
}
答案 1 :(得分:2)
这是一个很好的问题。
我以为我在某个地方看到了“错误类型可以桥接到NSError”,但这一定是Xcode或一些在线教程。
幸运的是我是从swift/NSError.swift找到的。
// NSError and CFError conform to the standard Error protocol. Compiler
// magic allows this to be done as a "toll-free" conversion when an NSError
// or CFError is used as an Error existential.
extension NSError : Error {
@nonobjc
public var _domain: String { return domain }
@nonobjc
public var _code: Int { return code }
@nonobjc
public var _userInfo: AnyObject? { return userInfo as NSDictionary }
/// The "embedded" NSError is itself.
@nonobjc
public func _getEmbeddedNSError() -> AnyObject? {
return self
}
}
extension CFError : Error {
public var _domain: String {
return CFErrorGetDomain(self) as String
}
public var _code: Int {
return CFErrorGetCode(self)
}
public var _userInfo: AnyObject? {
return CFErrorCopyUserInfo(self) as AnyObject
}
/// The "embedded" NSError is itself.
public func _getEmbeddedNSError() -> AnyObject? {
return self
}
}
答案 2 :(得分:-2)
HashSet hs = new HashSet();
hs.addAll(demoArrayList); // demoArrayList= name of arrayList from which u want
to remove duplicates
demoArrayList.clear();
demoArrayList.addAll(hs);