【问题标题】:Bridging Swift & Objective-C protocols?桥接 Swift 和 Objective-C 协议?
【发布时间】:2014-06-04 21:34:50
【问题描述】:

到目前为止,将 Swift 连接到 Objective-C 是非常痛苦的。 编译器对包括整数类型在内的所有类型都是无情的。 例如,如果您草率地将某些内容声明为 (int) 而不是 (NSInteger),您将收到一个编译错误,即找不到该函数。

示例:我在 PixelMapUI.h 标头中声明了这个现有的 Objective-C 协议:

@protocol DeleteKeyDelegate <NSTableViewDelegate>
- ( void ) deleteKeyPressed: ( NSTableView * ) view onRow: ( int ) rowIndex;
@end

在我的新 Swift 课程中,我正在尝试这样做:

extension NSTableView {

override func keyDown( event : NSEvent ) {
  var obj : NSTableViewDelegate = delegate()
  var obj2 = obj as? DeleteKeyDelegate;

  let characters : NSString = event.characters;
  var firstChar = Int(characters.characterAtIndex( 0 ));
  // if the user pressed delete and the delegate supports deleteKeyPressed
  if ( ( firstChar == NSDeleteFunctionKey ||
        firstChar == NSDeleteCharFunctionKey ||
        firstChar == NSDeleteCharacter) )
  {
     if let keyObj = obj as? DeleteKeyDelegate {
         keyObj.deleteKeyPressed( self, onRow: selectedRow() );
     }
  }

}

这会产生编译器错误:

“找不到成员'deleteKeyPressed'

在磕磕绊绊之后,我终于将我的 Objective-C 协议从 (int) 更改为 (NSInteger) 并且它开始工作了。

** 叹息 ** 如果 Swift 会像 Java 一样无情,那么当其他每一行代码都有一个类型转换整数时,它就不会是漂亮的代码。 是否有一些选项可以让 Swift 不将整数类型不匹配视为错误?

【问题讨论】:

  • 好吧,'int' 不是 'NSInteger',如果你不区分两者,就会出现很多疯狂的错误。记住 Ariane 5 的爆炸 :) 使用 swift 是一种很好的方法,可以确保您不会断言数字的大小并避免在从一种架构转换到另一种架构时破坏代码。当你来自一种松散类型的语言时可能会很烦人,但你很快就会喜欢它:)
  • 同意@StephanePhilipakis。 Swift 的重点是在编译时绝对确保代码中没有错误。并且int 不能保证与NSInteger 相同,如果您将它们混合在您的C 或Objective C 代码中,那 错误。编译器未捕获的错误。您的代码可能有效,也可能无效。它现在可能工作,当用户升级到下一个版本的操作系统时停止工作。使用 C 和 ObjectiveC,您只会在运行时(可能在将来)发生错误时看到错误。使用 Swift,您在今天编译代码时就会看到它。
  • 一个问题是,当 swift 编译器告诉您 objc 方法不存在时,它并没有帮助。它确实存在,只是类型略有不同。编译器需要指出错误的原因,特别是对于不匹配的数字类型。数字类型的类型安全有时很重要。我担心那些试图将 c 代码移植到 swift 的人会引入错误。 Swift 强制你对每一行代码进行类型转换,使代码不可读。更糟糕的是,搬运工会尝试更改工作的 objc 代码,从而引入错误。

标签: objective-c protocols swift


【解决方案1】:

这个编译并且工作得很好。 我知道那里有一个“魔法常数”;-) (51 -> Backspace),但为了演示,只有 if 语句是相关的;-)

@objc protocol MyTableViewDelegate {
    func deleteKeyPressed(row:Int)
}

extension NSTableView {
    override public func keyDown(theEvent: NSEvent!) {
        if let ds = self.delegate() as? MyTableViewDelegate {
            if theEvent.keyCode==51 {
                ds.deleteKeyPressed(self.selectedRow)
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多