【问题标题】:Error Handling an Objective-C framework in Swift Language用 Swift 语言处理 Objective-C 框架的错误
【发布时间】:2015-11-18 18:59:48
【问题描述】:

我正在使用 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 $$$$$[$$$$$:$$$$$] * 由于未捕获的异常“PortException”而终止应用程序,原因:“Native GetParsedStatusEx”失败的' * 首先抛出调用栈: (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:以未捕获的 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.h的完整代码https://github.com/gabebear/receiptbooth/blob/master/StarIO.framework/Headers/SMPort.h

【问题讨论】:

  • 你不能在 Swift 中捕获异常。我会在objective-c 中为SMPort 编写一个包装器,它以与Swift 兼容的方式捕获异常并抛出错误,然后从Swift 调用包装器代码

标签: ios objective-c swift swift2 swift2.1


【解决方案1】:

这是一个很好的问题!这是一个需要解决的合法问题。不幸的是,您目前无法实现这一目标。原因如下:

Swift 异常处理与异常无关。事实上,你无法捕捉到 NSException,这是 Obj-C 端提出的。 Swift 捕获 NSError,它实际上(在 Swift 中)是一个枚举。长话短说,在 Objective-C 中有两种处理错误的模式: 1. 引发 NSException 2. 返回 NSError

正如我所解释的,您无法处理使用第一种方法引发的错误。因此,从字面上看,您必须使用 NSError 修改您的 Objective-C 代码以符合第二种方法。

一些不错的链接:

https://www.bignerdranch.com/blog/error-handling-in-swift-2/ https://forums.developer.apple.com/thread/7582

【讨论】:

    【解决方案2】:

    感谢@Peyman 和@dan,我编写了两个新的Objective-C 文件,在其中我实现了一个新方法(扩展SMPort 类),该方法捕获错误并返回NSError

    SMPort+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
     }
    

    非常感谢!

    【讨论】:

      猜你喜欢
      • 2012-05-27
      • 2019-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-27
      • 2014-08-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多