Swift protocol extension: fatal error: can't unsafeBitCast between types of different sizes
Swift protocol extension: fatal error: can't unsafeBitCast between types of different sizes
我定义了一个带有协议扩展的协议来简化 NSError
的使用。
protocol NSErrorConvertible: RawRepresentable {
var domain: String { get }
var localizedDescription: String { get }
}
extension NSErrorConvertible where RawValue == Int {
func generateError(parameters parameters: [String] = []) -> NSError {
let error = self.generateError(format: self.localizedDescription, parameters: parameters)
return error
}
func generateError(format format: String, parameters: [String] = []) -> NSError {
let description = String(format: format, arguments: parameters) // <-- BREAK
let error = NSError(domain: self.domain, code: self.rawValue, localizedDescription: description)
return error
}
}
extension NSError {
convenience init(domain: String, code: Int, localizedDescription: String) {
let userInfo = [NSLocalizedDescriptionKey : localizedDescription]
self.init(domain: domain, code: code, userInfo: userInfo)
}
}
协议的使用方式如下:
enum DefaultEngineErrors: Int, NSErrorConvertible {
case ImagesNotSupported
case FooDoesNotHaveABar
case NilBar
var domain: String { return "DefaultEngineErrors" }
var localizedDescription: String {
switch self {
case .ImagesNotSupported: return "%s: Images are not supported."
case .FooDoesNotHaveABar: return "%s: Foo does not have a bar."
case .NilBar: return "%s: The bar is nil."
}
}
}
下面是协议扩展方法的调用方式:
let error = DefaultEngineErrors.FooDoesNotHaveABar.generateError(parameters: ["\(foo.id)"])
当此代码为 运行 时,调试器在第二个 generateError
扩展函数中构建描述的行中断,调试器控制台中显示以下消息:
致命错误:无法在不同大小的类型之间进行 unsafeBitCast
请注意,如果我将对 String(format:)
的调用替换为 format
,一切正常。
问:我在这里做的有什么问题吗?
除此之外,我无法检查协议扩展中的参数。当我尝试时显示以下消息:
(lldb) po format
error: <EXPR>:1:1: error: non-nominal type '$__lldb_context' (aka 'Self') cannot be extended
extension $__lldb_context {
^ ~~~~~~~~~~~~~~~
<EXPR>:15:5: error: value of type 'DefaultEngineErrors' has no member '$__lldb_wrapped_expr_54'
$__lldb_injected_self.$__lldb_wrapped_expr_54(
^~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
Swift string Array is not compatible with CVarArgType... or [CVarArgType]
尝试使用。
extension NSErrorConvertible where RawValue == Int {
func generateError(format format: String) -> NSError {
let error = NSError(domain: self.domain, code: self.rawValue, localizedDescription: format)
return error
}
func generateError(args : CVarArgType...) -> NSError {
let returnString = NSString(format: self.localizedDescription, arguments: getVaList(args)) as String
// let returnString = withVaList(args) {
// NSString(format: self.localizedDescription, arguments: [=10=])
// } as String
let error = generateError(format: returnString)
return error
}
}
enum DefaultEngineErrors: Int, NSErrorConvertible {
case ImagesNotSupported
case FooDoesNotHaveABar
case FooWithMultiPar
case NilBar
var domain: String { return "DefaultEngineErrors" }
var localizedDescription: String {
switch self {
case .ImagesNotSupported: return "%@: Images are not supported."
case .FooDoesNotHaveABar: return "%@: Foo does not have a bar."
case .FooWithMultiPar: return "%@:%@ Foo does not have a bar."
case .NilBar: return "%@: The bar is nil."
}
}
}
print(DefaultEngineErrors.FooDoesNotHaveABar.generateError("test"))
print(DefaultEngineErrors.FooWithMultiPar.generateError("test1","test2"))
勾选
我定义了一个带有协议扩展的协议来简化 NSError
的使用。
protocol NSErrorConvertible: RawRepresentable {
var domain: String { get }
var localizedDescription: String { get }
}
extension NSErrorConvertible where RawValue == Int {
func generateError(parameters parameters: [String] = []) -> NSError {
let error = self.generateError(format: self.localizedDescription, parameters: parameters)
return error
}
func generateError(format format: String, parameters: [String] = []) -> NSError {
let description = String(format: format, arguments: parameters) // <-- BREAK
let error = NSError(domain: self.domain, code: self.rawValue, localizedDescription: description)
return error
}
}
extension NSError {
convenience init(domain: String, code: Int, localizedDescription: String) {
let userInfo = [NSLocalizedDescriptionKey : localizedDescription]
self.init(domain: domain, code: code, userInfo: userInfo)
}
}
协议的使用方式如下:
enum DefaultEngineErrors: Int, NSErrorConvertible {
case ImagesNotSupported
case FooDoesNotHaveABar
case NilBar
var domain: String { return "DefaultEngineErrors" }
var localizedDescription: String {
switch self {
case .ImagesNotSupported: return "%s: Images are not supported."
case .FooDoesNotHaveABar: return "%s: Foo does not have a bar."
case .NilBar: return "%s: The bar is nil."
}
}
}
下面是协议扩展方法的调用方式:
let error = DefaultEngineErrors.FooDoesNotHaveABar.generateError(parameters: ["\(foo.id)"])
当此代码为 运行 时,调试器在第二个 generateError
扩展函数中构建描述的行中断,调试器控制台中显示以下消息:
致命错误:无法在不同大小的类型之间进行 unsafeBitCast
请注意,如果我将对 String(format:)
的调用替换为 format
,一切正常。
问:我在这里做的有什么问题吗?
除此之外,我无法检查协议扩展中的参数。当我尝试时显示以下消息:
(lldb) po format
error: <EXPR>:1:1: error: non-nominal type '$__lldb_context' (aka 'Self') cannot be extended
extension $__lldb_context {
^ ~~~~~~~~~~~~~~~
<EXPR>:15:5: error: value of type 'DefaultEngineErrors' has no member '$__lldb_wrapped_expr_54'
$__lldb_injected_self.$__lldb_wrapped_expr_54(
^~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
Swift string Array is not compatible with CVarArgType... or [CVarArgType]
尝试使用。
extension NSErrorConvertible where RawValue == Int {
func generateError(format format: String) -> NSError {
let error = NSError(domain: self.domain, code: self.rawValue, localizedDescription: format)
return error
}
func generateError(args : CVarArgType...) -> NSError {
let returnString = NSString(format: self.localizedDescription, arguments: getVaList(args)) as String
// let returnString = withVaList(args) {
// NSString(format: self.localizedDescription, arguments: [=10=])
// } as String
let error = generateError(format: returnString)
return error
}
}
enum DefaultEngineErrors: Int, NSErrorConvertible {
case ImagesNotSupported
case FooDoesNotHaveABar
case FooWithMultiPar
case NilBar
var domain: String { return "DefaultEngineErrors" }
var localizedDescription: String {
switch self {
case .ImagesNotSupported: return "%@: Images are not supported."
case .FooDoesNotHaveABar: return "%@: Foo does not have a bar."
case .FooWithMultiPar: return "%@:%@ Foo does not have a bar."
case .NilBar: return "%@: The bar is nil."
}
}
}
print(DefaultEngineErrors.FooDoesNotHaveABar.generateError("test"))
print(DefaultEngineErrors.FooWithMultiPar.generateError("test1","test2"))
勾选