Ale*_*erl 17 error-handling swift do-catch
如何处理未明确抛出的方法或代码的错误?
将其包装为do/catch块会导致编译器警告:
"'catch' block is unreachable because no errors are thrown in 'do' block"
Run Code Online (Sandbox Code Playgroud)
来自C#/ JAVA背景,至少可以说这是一个奇怪的事.作为开发人员,我应该能够在do/catch块中保护和包装任何代码块.仅仅因为方法未明确标记为"throw"并不意味着不会发生错误.
ERRORS 和 EXCEPTIONS 之间存在差异。Swift 只处理明确抛出的错误,并且没有处理异常的本机能力。正如其他人评论的那样,必须抛出错误,而您无法捕捉未抛出的内容。
相比之下,Objective-C @try-@catch 处理的是异常,而不是错误。一些 objc 方法可能会导致异常,但不会以任何方式向编译器声明它们。例如 FileHandle.write。此类异常与 Java 的 RuntimeException 更接近,后者也不需要声明。
在某些情况下,例如文件处理,在 Swift 中干净地处理异常会很好,并且可以使用 Objective-C 包装器。见http://stackoverflow.com/questions/34956002/how-to-properly-handle-nsfilehandle-exceptions-in-swift-2-0
代码转载在这里:
#ifndef ExceptionCatcher_h
#define ExceptionCatcher_h
#import <Foundation/Foundation.h>
NS_INLINE NSException * _Nullable tryBlock(void(^_Nonnull tryBlock)(void)) {
@try {
tryBlock();
}
@catch (NSException *exception) {
return exception;
}
return nil;
}
#endif /* ExceptionCatcher_h */
Run Code Online (Sandbox Code Playgroud)
然后从 Swift 调用它:
let exception = tryBlock {
// execute dangerous code, e.g. write to a file handle
filehandle.write(data)
}
if exception != nil {
// deal with exception which is of type NSException
}
Run Code Online (Sandbox Code Playgroud)
面对无法抛出的方法抛出的异常。发现此异常是从API的Objective-C部分抛出的。因此,您应该使用Objective-C以旧样式捕获它。
首先,创建init方法中包含多个块的Objective-C类-进行尝试,捕获并最终完成。
#import <Foundation/Foundation.h>
/**
Simple class for catching Objective-c-style exceptions
*/
@interface ObjcTry : NSObject
/**
* Initializeer
*
* @param tryBlock
* @param catchBlock
* @param finallyBlock
*
* @return object
*/
- (_Nonnull id)initWithTry:(nonnull void(^)(void))tryBlock catch:(nonnull void(^)( NSException * _Nonnull exception))catchBlock finally:(nullable void(^)(void))finallyBlock;
@end
Run Code Online (Sandbox Code Playgroud)
在.m文件中:
#import "ObjcTry.h"
@implementation ObjcTry
- (_Nonnull id)initWithTry:(nonnull void(^)(void))tryBlock catch:(nonnull void(^)( NSException * _Nonnull exception))catchBlock finally:(nullable void(^)(void))finallyBlock
{
self = [super init];
if (self) {
@try {
tryBlock ? tryBlock() : nil;
}
@catch (NSException *exception) {
catchBlock ? catchBlock(exception) : nil;
}
@finally {
finallyBlock ? finallyBlock() : nil;
}
}
return self;
}
@end
Run Code Online (Sandbox Code Playgroud)
其次,将其标题添加到“桥接标题”文件中。
#import "ObjcTry.h"
Run Code Online (Sandbox Code Playgroud)
并在这样的快速代码中使用它:
var list: [MyModel]!
_ = ObjcTry(withTry: {
// this method throws but not marked so, you cannot even catch this kind of exception using swift method.
if let items = NSKeyedUnarchiver.unarchiveObject(with: data) as? [MyModel] {
list = items
}
}, catch: { (exception: NSException) in
print("Could not deserialize models.")
}, finally: nil)
Run Code Online (Sandbox Code Playgroud)
您在Swift中无法提出的问题,因为Swift无法处理运行时错误,例如越界,访问冲突或运行时强制解包失败.如果发生任何严重的编程错误,您的申请将终止.
一些指示:
长话短说:不要在Swift中快速处理错误处理.永远保持安全.
解决方法:如果绝对必须捕获运行时错误,则必须使用进程边界来保护.运行另一个程序/进程并使用管道,套接字等进行通信.
我怀疑您想捕获未显式标记为“ throws”的错误。
这是没有道理的。除了明确标记为“ throws”的错误外,您无法捕获其他错误。因此,此警告有效。
对于此示例,如果执行,fatal error: Index out of range
将发生。这是运行时错误,您无法捕获它。
对于此示例,您应该检查像这样的元素大小,而不是执行try-catch错误处理:
归档时间: |
|
查看次数: |
7125 次 |
最近记录: |