【问题标题】:'does not have member' when calling objective C setter method from Swift从 Swift 调用目标 C setter 方法时“没有成员”
【发布时间】:2015-03-14 13:30:49
【问题描述】:

将目标 C robbiehanson/XMPPFramework 导入 swift 项目后(设置构建设置、桥接头等)。我可以在导入的类中调用普通方法并直接设置属性。

但是,某些设置属性的实例方法会立即导致错误,就好像它们在我调用它们的实例中不存在一样。例如:

- (void)setMyJID:(XMPPJID *)newMyJID
{
    [self setMyJID_setByClient:newMyJID];
}

甚至是实际进行设置的setMyJID_setByClient:newMyJID 方法。

在我看过的两个单独的目标 c 示例项目中,setMyJID 方法是从其他类调用的。但是,虽然我可以调用类上的其他实例方法,但我不能调用这个。由于我对objective c不是很熟悉,我认为这可能是因为它没有在头文件中声明,导致一些swift特定的问题,但尝试为其添加声明并没有帮助。

我可以直接设置相关属性,但这不仅是不可取的,我也想了解为什么我不能调用某些方法。

我正在尝试像这样对 XMPPStream 类的实例进行调用

    //This shows immediate error: XMPPStream does not have a member named 'setMyJID'
    stream.setMyJID(XMPPJID.jidWithString(someXMPPAddress)
    // This works perfectly
    stream.myJID = (XMPPJID.jidWithString(someXMPPAddress))

任何帮助将不胜感激。

【问题讨论】:

    标签: objective-c swift compiler-errors getter-setter


    【解决方案1】:

    XMPPStream 类中,myJID 声明如下:

    @property (readwrite, copy) XMPPJID *myJID;
    

    在 Objective-C 中,这意味着在 XMPPStream 类上实际上有两个方法符合以下签名:

    - (XMPPJID *)myJID;
    - (void)setMyJID:(XMPPJID *)myJID;
    

    因此,在 Objective-C 代码中,您可以像调用任何其他方法一样调用它们。但是,如您所知,您还可以选择使用称为“点表示法”的语言中的语法糖:

    // getter with dot notation
    XMPPJID *jid = stream.myJID;
    // setter with dot notation
    stream.myJID = jid;
    

    然而,在 Objective-C 中,这些点符号表达式直接翻译为对 getter 和 setter 的调用。他们只是在那里看起来不错。

    在 Swift 中情况有所不同。当你有一个属性时,像这样:

    var myJID: XMPPJID
    

    意味着存在单独的getter和setter方法,就像你想象的那样:

    func myJID() -> XMPPJID {}
    func setMyJID(jid: XMPPJID) {}
    

    在 Swift 中,您必须使用点语法访问属性。

    知道了这一点,你的问题就变得很明显了。当你尝试时:

    stream.setMyJID(XMPPJID.jidWithString(someXMPPAddress)
    

    Swift 尝试运行stream 的实例方法setMyJID,结果发现它不存在!这当然是:

    stream.myJID = (XMPPJID.jidWithString(someXMPPAddress))
    

    完美运行,因为您正在按照 Swift 的要求设置属性。


    除了教育之外,您有时可能会看到在从 Swift 访问 Objective-C 属性时,您不仅可以,而且必须使用 getter 和 setter 方法 - 点表示法不会甚至工作!这似乎完全违反直觉,但发生这种情况是有充分理由的。我能想到的一个例子是详细命名的UIView 属性translatesAutoresizingMaskIntoConstraints,用于视图布局。如果你尝试在 Swift 中使用它,像这样:

    // Set translatesAutoresizingMaskIntoConstraints to false on self
    translatesAutoresizingMaskIntoConstraints = false
    

    你会得到一个编译错误!具体来说,

    无法分配给“self”中的“translatesAutoresizingMaskIntoConstraints”

    为什么?答案就在UIView 标头中:

    - (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES
    - (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag NS_AVAILABLE_IOS(6_0);
    

    事实证明,与 Cocoa 框架中的许多其他“属性”一样,实际上只是一对看起来类似于属性访问器的方法。由于 Objective-C 如何将点表示法转换为方法调用,您以前不会注意到。不过,现在 Swift 更加严格了——要获取和设置这个“属性”,您必须调用适当的方法。

    【讨论】:

      猜你喜欢
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多