sil*_*vsk 65 cocoa-touch exception foundation nsexception swift
Swift中的以下代码引发NSInvalidArgumentException异常:
task = NSTask()
task.launchPath = "/SomeWrongPath"
task.launch()
Run Code Online (Sandbox Code Playgroud)
我该如何捕捉异常?据我所知,Swift中的try/catch是针对Swift中抛出的错误,而不是针对像NSTask这样的对象引发的NSExceptions(我猜这是用ObjC编写的).我是Swift的新手,所以可能是我错过了一些明显的东西......
编辑:这是一个关于bug的雷达(特别是对于NSTask):openradar.appspot.com/22837476
fre*_*tag 121
下面是一些将NSExceptions转换为Swift 2错误的代码.
现在你可以使用了
do {
try ObjC.catchException {
/* calls that might throw an NSException */
}
}
catch {
print("An error ocurred: \(error)")
}
Run Code Online (Sandbox Code Playgroud)
ObjC.h:
#import <Foundation/Foundation.h>
@interface ObjC : NSObject
+ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error;
@end
Run Code Online (Sandbox Code Playgroud)
ObjC.m
#import "ObjC.h"
@implementation ObjC
+ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error {
@try {
tryBlock();
return YES;
}
@catch (NSException *exception) {
*error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:exception.userInfo];
return NO;
}
}
@end
Run Code Online (Sandbox Code Playgroud)
不要忘记将其添加到"*-Bridging-Header.h":
#import "ObjC.h"
Run Code Online (Sandbox Code Playgroud)
BPC*_*orp 12
我建议创建一个C函数来捕获异常并返回NSError.然后,使用此功能.
该函数可能如下所示:
NSError *tryCatch(void(^tryBlock)(), NSError *(^convertNSException)(NSException *))
{
NSError *error = nil;
@try {
tryBlock();
}
@catch (NSException *exception) {
error = convertNSException(exception);
}
@finally {
return error;
}
}
Run Code Online (Sandbox Code Playgroud)
有了一点桥接帮助,你只需要打电话:
if let error = tryCatch(task.launch, myConvertFunction) {
print("An exception happened!", error.localizedDescription)
// Do stuff
}
// Continue task
Run Code Online (Sandbox Code Playgroud)
注意:我没有真正测试它,我找不到一个快速简单的方法在Playground中使用Objective-C和Swift.
TL; DR:使用Carthage包含 https://github.com/eggheadgames/SwiftTryCatch 或CocoaPods以包含 https://github.com/ravero/SwiftTryCatch.
然后你可以使用这样的代码,而不用担心会崩溃你的应用程序:
import Foundation
import SwiftTryCatch
class SafeArchiver {
class func unarchiveObjectWithFile(filename: String) -> AnyObject? {
var data : AnyObject? = nil
if NSFileManager.defaultManager().fileExistsAtPath(filename) {
SwiftTryCatch.tryBlock({
data = NSKeyedUnarchiver.unarchiveObjectWithFile(filename)
}, catchBlock: { (error) in
Logger.logException("SafeArchiver.unarchiveObjectWithFile")
}, finallyBlock: {
})
}
return data
}
class func archiveRootObject(data: AnyObject, toFile : String) -> Bool {
var result: Bool = false
SwiftTryCatch.tryBlock({
result = NSKeyedArchiver.archiveRootObject(data, toFile: toFile)
}, catchBlock: { (error) in
Logger.logException("SafeArchiver.archiveRootObject")
}, finallyBlock: {
})
return result
}
}
Run Code Online (Sandbox Code Playgroud)
@BPCorp接受的答案按预期工作,但正如我们所发现的,如果您尝试将此Objective C代码合并到大多数Swift框架中然后运行测试,那么事情会变得有趣.我们遇到了无法找到类函数的问题(错误:使用未解析的标识符).因此,由于这个原因,以及一般易用性,我们将其打包为一般用途的Carthage库.
奇怪的是,我们可以在其他地方使用Swift + ObjC框架而没有任何问题,它只是对框架的单元测试而言正在挣扎.
要求PR!(让它成为一个组合CocoaPod和Carthage构建,并进行一些测试会很好).
| 归档时间: |
|
| 查看次数: |
21656 次 |
| 最近记录: |