【问题标题】:Swift 2.0 and objective-c compatibility method returns Bool with parameter NSErrorSwift 2.0 和objective-c 兼容方法返回带有参数NSError 的Bool
【发布时间】:2016-06-05 15:51:55
【问题描述】:

我正在开发一个使用objective-c 框架的新项目,所有新代码都在Swift 中。我遇到了一个有趣的兼容性问题。问题出现在 Swift 2.0 中,其中 objective-c 中返回 BOOL 并采用 NSError 参数的任何方法都被转换为返回 VoidSwift 中的 Voidthrows 的方法。这种翻译的一个例子是NSManagedObjectContext save 方法,现在在 Swift 中:

public func save() throws

当代码从 Swift 调用并且实现也在 Swift 中时,这不是问题。

我面临的问题是我不能(或不应该)在 Objective-c 中修改遵循相同模式的框架。在这种情况下,我正在实现在objective-c 协议中定义的方法,当在Swift 中实现它时,让编译器满意的唯一方法是返回 Void 并抛出一些东西,当objective-c 调用我的方法时,它在内部捕获错误,返回值变为NO,这是我想要的行为。

但是现在告诉我发生了什么的NSError 是 nil,似乎没有办法从 Swift 中设置它,因为它甚至没有传入参数,并且是遵守协议的唯一方法是把它拿出来。我不仅在抛出的异常中看不到消息,而且现在我也看不到 NSError。我只知道调用失败,但没有任何消息可以记录/显示失败的原因,或者在某些失败条件下重试。

我一直在寻找一种方法,Objective-c 可以将ErrorType 连接到NSError,但根本找不到任何东西。就像它在内部捕获 ErrorType 并将返回值设置为 NO 一样。

有没有办法在不改变objective-c协议定义的情况下解决这个问题?

【问题讨论】:

  • 协议是用 Swift 还是 Objective-C 定义的,它是什么样的?是用 Swift 还是 Objective-C 实现的? – 最后,你不能直接从 Swift 中抛出一个NSError(...) 吗?
  • @MartinR 该协议是在 Objective-C 中定义的,该方法类似于 - (BOOL)myMethod(some params.... NSError *__autoreleasing *error)。实现在 Swift 中,我可以抛出 NSError 但调用协议实现的目标 c 代码只会捕获错误并将返回值设置为 NO,我需要一种方法来查看目标 c 代码中的 NSError,框架使用它来报告错误。
  • 我无法(此时)修改现有的objective-c 代码,其中定义了协议以及从objective-c 调用协议方法(在Swift 中实现)的位置。
  • 我无法重现该问题,也许我误解了它。 – 如果 Swift 函数抛出 throw NSError(domain: "domain", code: 1234, userInfo: ["foo" : "bar"]) 并从 Objective-C 调用为 [obj myMethod:... error:&error];error 设置为抛出的 NSError。 – 一个独立的可重现示例会很有帮助!
  • @MartinR 我犯了一个错误,如果我抛出一个 NSError,它实际上可以正常工作,谢谢!请随时在下面发布答案。

标签: objective-c swift error-handling compatibility nserror


【解决方案1】:

给定一个协议定义

@protocol MyProtocol <NSObject>
- (BOOL)myMethod:(NSInteger)x error:(NSError *__autoreleasing *)error;
@end

你可以在 Swift 中实现一个符合要求的类并抛出一个NSError

class SwClass : NSObject, MyProtocol {

    func myMethod(x: Int) throws {
        if x < 0 {
            throw NSError(domain: "my.domain", code: 1234, userInfo: ["error" : "called with negative argument"])
        }
    }
}

当从 Objective-C 调用时,错误被分配给传递的 NSError变量:

-(void)foo {
    SwClass *obj = [[SwClass alloc] init];
    NSError *error;
    if (![obj myMethod:-3 error:&error]) {
        NSLog(@"%@", error);
    }
}

因此,协议方法是否实现并不重要 在 Objective-C 或 Swift 中。

【讨论】:

    猜你喜欢
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多