'没有会员'从Swift调用Objective C setter方法时

时间:2015-03-14 13:30:49

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

将目标C robbiehanson / XMPPFramework导入swift项目(设置构建设置,桥接标题等)。我能够在导入的类中调用常规方法并直接设置属性。

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

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

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

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

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

我试图像这样

在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))

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分: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试图运行setMyJID的实例方法stream,并且正确地发现它不存在!这当然是:

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更严格 - 要获得并设置这个“属性”,你必须调用适当的方法。