很多时候,我会Error从框架中收到一个Swift 对象,这真的是一个NSError.
为了访问它的信息(例如code),我需要将其转换为NSError:
(error as NSError).code == ....
Run Code Online (Sandbox Code Playgroud)
为什么这只是一个无条件的as?如果我设计我自己的符合的错误类Error,它不一定是一个NSError,那么这怎么可能是执行这个演员的正确方法?
类型系统中是否存在某种特殊情况?这是一个向下倾斜,表现得像一个向上倾斜.
我相信Error可以转换为的能力NSError被硬编码到编译器中,而实际的桥接是在Swift运行时中实现的.
在runtime/ErrorObject.mm,我发现这个评论:
// 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
Run Code Online (Sandbox Code Playgroud)
而这个功能:
/// 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);
...
}
Run Code Online (Sandbox Code Playgroud)
该ErrorHandling.rst文件说,这对理由:
应当可以把符合任意夫特枚举
Error成NSError通过使用限定类型名称为域密钥,则枚举作为错误代码,并转动到有效载荷的用户数据.
(部分文件可能已过时.)
而这是(我认为)的类型检查至少一部分人的信息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();
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个很好的问题。
我以为我在某处看到了“错误类型可以桥接到 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
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2374 次 |
| 最近记录: |