使用 Swift 语言处理 Objective-C 框架时出错
Error Handling an Objective-C framework in Swift Language
我正在使用 Objective-C 框架创建 iOS Swift 应用程序。
框架头文件(SMPort.h):
// ... do all the import //
@interface PortException : NSException
{
}
@end
@interface PortInfo : NSObject
- (id)initWithPortName:(NSString *)portName_ macAddress:(NSString *)macAddress_ modelName:(NSString *)modelName_;
@property(retain, readonly) NSString *portName;
@property(retain, readonly) NSString *macAddress;
@property(retain, readonly) NSString *modelName;
@property(readonly, getter=isConnected) BOOL connected;
@end
@interface SMPort : NSObject {
void * m_port;
WBluetoothPort* wBluetoothPort;
BluetoothPort* bluetoothPort;
NSString * m_portName;
NSString * m_portSettings;
int m_ioTimeoutMillis;
BOOL checkedBlockSupport;
}
@property(assign, readwrite, nonatomic) u_int32_t endCheckedBlockTimeoutMillis;
// Initializer and staff methods...
/*!
* This function retreives the device's detailed status.
*
* @param starPrinterStatus Pointer to a StarPrinterStatus_n structure where the devices detailed status is written
* (either StarPrinterStatus_0, StarPrinterStatus_1, or StarPrinterStatus_2).
* @param level Integer designating the level of status structure (either 0, 1, or 2).
*
* @note Throws PortException on failure.
*/
- (void)getParsedStatus:(void *)starPrinterStatus :(u_int32_t)level;
// The other methods...
我阅读了框架文档并找到了这段 Objective-C 代码(完美运行):
@try
{
[starPort getParsedStatus:&status :2];
}
@catch (PortException *exception){
// Print error
}
所以我尝试在 Swift 2.1 中做这样的事情:
do{
try starPort.getParsedStatus(status , 2)
}
catch is PortException{
print("error")
}
但是当错误发生时,编译器停止了应用程序,说我没有捕获到那个错误:
2015-11-18 18:59:51.297 $$$$$[$$$$$:$$$$$] * Terminating app due to uncaught exception 'PortException', reason: 'Native GetParsedStatusEx failed'
* First throw call stack:
(0x2524a67b 0x36e76e17 0xa3af7 0x6f378 0x6f3d8 0x6fbc0 0x6fd10 0x6ef00 0x87bf8 0x87d80 0x29371559 0x293714e9 0x293594ff 0x29370e45 0x29370abf 0x2936947f 0x2933a561 0x29338bdb 0x2520dbff 0x2520d7ed 0x2520bb5b 0x2515f119 0x2515ef05 0x2e2fcac9 0x293a1f15 0x7f410 0x375e5873)
libc++abi.dylib: terminating with uncaught exception of type PortException
我也试过这样的:
func doGPS() throws { starPort.getParsedStatus(status ,2) }
func test() {
do {
try doGPS()
} catch is PortException{
print("Error")
} catch{
print("WTF? : \(error)")
}
}
test()
得到相同的结果...
那么,我怎样才能在 Swift 2.1 中捕捉到这个错误?
这里是SMPort.hhttps://github.com/gabebear/receiptbooth/blob/master/StarIO.framework/Headers/SMPort.h
的完整代码
这是个很好的问题!这是一个需要解决的合法问题。不幸的是,您目前无法实现这一目标。原因如下:
Swift异常处理与Exceptions无关。事实上,您无法捕获 NSException,这是在 Obj-C 端引发的。 Swift 捕获 NSError,它实际上(在 Swift 中)是一个枚举。长话短说,在 Objective-C 中有两种处理错误的模式:1. 引发 NSException 2. 返回 NSError
正如我所解释的,您无法处理使用第一种方法引发的错误。所以,从字面上看,你必须修改你的 Objective-C 代码以符合第二种方法,使用 NSError.
一些不错的链接:
https://www.bignerdranch.com/blog/error-handling-in-swift-2/
https://forums.developer.apple.com/thread/7582
所以,感谢@Peyman 和@dan,我写了两个新的 Objective-C 文件,我在其中实现了一个新方法(扩展 SMPort
class)来捕获错误和returns一个NSError
SM端口+Handler.h
#import <Foundation/Foundation.h>
#import <StarIO/SMPort.h>
@interface SMPort ( Handler )
- (BOOL)getParsedStatusThrowing:(void *)starPrinterStatus
level:(u_int32_t)level
didFailWithError:(NSError **)error;
@end
SMPort+Handler.m
#import "SMPort+Handler.h"
@implementation SMPort ( Handler )
- (BOOL)getParsedStatusThrowing:(void *)starPrinterStatus
level:(u_int32_t)level
didFailWithError:(NSError **)error
{
@try
{
[self getParsedStatus:&starPrinterStatus :level];
return TRUE;
}
@catch (PortException *exception){
NSMutableDictionary* details = [NSMutableDictionary dictionary];
// exemption.name in my case should be PortExeption
[details setValue:exception.name forKey:NSLocalizedDescriptionKey];
*error = [NSError errorWithDomain:@"somedomain" code:100 userInfo:details];
return FALSE;
}
}
@end
现在,我只需做(在我的 Swift 代码中):
do{
//starPort.getParsedStatus(status ,2)
try starPort.getParsedStatusThrowing(status, level: 2)
defer{
// Release the port in any case.
SMPort.releasePort(starPort)
}
}catch{
print(error)
// do staff like return
}
非常感谢!
我正在使用 Objective-C 框架创建 iOS Swift 应用程序。
框架头文件(SMPort.h):
// ... do all the import //
@interface PortException : NSException
{
}
@end
@interface PortInfo : NSObject
- (id)initWithPortName:(NSString *)portName_ macAddress:(NSString *)macAddress_ modelName:(NSString *)modelName_;
@property(retain, readonly) NSString *portName;
@property(retain, readonly) NSString *macAddress;
@property(retain, readonly) NSString *modelName;
@property(readonly, getter=isConnected) BOOL connected;
@end
@interface SMPort : NSObject {
void * m_port;
WBluetoothPort* wBluetoothPort;
BluetoothPort* bluetoothPort;
NSString * m_portName;
NSString * m_portSettings;
int m_ioTimeoutMillis;
BOOL checkedBlockSupport;
}
@property(assign, readwrite, nonatomic) u_int32_t endCheckedBlockTimeoutMillis;
// Initializer and staff methods...
/*!
* This function retreives the device's detailed status.
*
* @param starPrinterStatus Pointer to a StarPrinterStatus_n structure where the devices detailed status is written
* (either StarPrinterStatus_0, StarPrinterStatus_1, or StarPrinterStatus_2).
* @param level Integer designating the level of status structure (either 0, 1, or 2).
*
* @note Throws PortException on failure.
*/
- (void)getParsedStatus:(void *)starPrinterStatus :(u_int32_t)level;
// The other methods...
我阅读了框架文档并找到了这段 Objective-C 代码(完美运行):
@try
{
[starPort getParsedStatus:&status :2];
}
@catch (PortException *exception){
// Print error
}
所以我尝试在 Swift 2.1 中做这样的事情:
do{
try starPort.getParsedStatus(status , 2)
}
catch is PortException{
print("error")
}
但是当错误发生时,编译器停止了应用程序,说我没有捕获到那个错误:
2015-11-18 18:59:51.297 $$$$$[$$$$$:$$$$$] * Terminating app due to uncaught exception 'PortException', reason: 'Native GetParsedStatusEx failed' * First throw call stack: (0x2524a67b 0x36e76e17 0xa3af7 0x6f378 0x6f3d8 0x6fbc0 0x6fd10 0x6ef00 0x87bf8 0x87d80 0x29371559 0x293714e9 0x293594ff 0x29370e45 0x29370abf 0x2936947f 0x2933a561 0x29338bdb 0x2520dbff 0x2520d7ed 0x2520bb5b 0x2515f119 0x2515ef05 0x2e2fcac9 0x293a1f15 0x7f410 0x375e5873) libc++abi.dylib: terminating with uncaught exception of type PortException
我也试过这样的:
func doGPS() throws { starPort.getParsedStatus(status ,2) }
func test() {
do {
try doGPS()
} catch is PortException{
print("Error")
} catch{
print("WTF? : \(error)")
}
}
test()
得到相同的结果...
那么,我怎样才能在 Swift 2.1 中捕捉到这个错误?
这里是SMPort.hhttps://github.com/gabebear/receiptbooth/blob/master/StarIO.framework/Headers/SMPort.h
的完整代码这是个很好的问题!这是一个需要解决的合法问题。不幸的是,您目前无法实现这一目标。原因如下:
Swift异常处理与Exceptions无关。事实上,您无法捕获 NSException,这是在 Obj-C 端引发的。 Swift 捕获 NSError,它实际上(在 Swift 中)是一个枚举。长话短说,在 Objective-C 中有两种处理错误的模式:1. 引发 NSException 2. 返回 NSError
正如我所解释的,您无法处理使用第一种方法引发的错误。所以,从字面上看,你必须修改你的 Objective-C 代码以符合第二种方法,使用 NSError.
一些不错的链接:
https://www.bignerdranch.com/blog/error-handling-in-swift-2/ https://forums.developer.apple.com/thread/7582
所以,感谢@Peyman 和@dan,我写了两个新的 Objective-C 文件,我在其中实现了一个新方法(扩展 SMPort
class)来捕获错误和returns一个NSError
SM端口+Handler.h
#import <Foundation/Foundation.h>
#import <StarIO/SMPort.h>
@interface SMPort ( Handler )
- (BOOL)getParsedStatusThrowing:(void *)starPrinterStatus
level:(u_int32_t)level
didFailWithError:(NSError **)error;
@end
SMPort+Handler.m
#import "SMPort+Handler.h"
@implementation SMPort ( Handler )
- (BOOL)getParsedStatusThrowing:(void *)starPrinterStatus
level:(u_int32_t)level
didFailWithError:(NSError **)error
{
@try
{
[self getParsedStatus:&starPrinterStatus :level];
return TRUE;
}
@catch (PortException *exception){
NSMutableDictionary* details = [NSMutableDictionary dictionary];
// exemption.name in my case should be PortExeption
[details setValue:exception.name forKey:NSLocalizedDescriptionKey];
*error = [NSError errorWithDomain:@"somedomain" code:100 userInfo:details];
return FALSE;
}
}
@end
现在,我只需做(在我的 Swift 代码中):
do{
//starPort.getParsedStatus(status ,2)
try starPort.getParsedStatusThrowing(status, level: 2)
defer{
// Release the port in any case.
SMPort.releasePort(starPort)
}
}catch{
print(error)
// do staff like return
}
非常感谢!