'does not have member' 从 Swift 调用 objective C setter 方法时

'does not have member' when calling objective C setter method from Swift

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

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

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

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

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

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

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

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

如有任何帮助,我们将不胜感激。

XMPPStreamclass中,myJID声明如下:

@property (readwrite, copy) XMPPJID *myJID;

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

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

因此,从 Objective-C 代码中,您可以像调用任何其他方法一样调用它们。但是,如您所知,您还可以选择使用称为 "dot notation":

的语言中的语法糖
// 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 方法 - 点符号甚至不起作用!这似乎完全违反直觉,但这是有充分理由的。我能想到的一个例子是 verbosely-named UIView 属性 translatesAutoresizingMaskIntoConstraints,用于视图布局。如果你尝试在 Swift 中使用它,就像这样:

// Set translatesAutoresizingMaskIntoConstraints to false on self
translatesAutoresizingMaskIntoConstraints = false

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

Cannot assign to 'translatesAutoresizingMaskIntoConstraints' in 'self'

为什么?答案就在UIView headers:

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

事实证明,这个 "property," 与 Cocoa 框架中的许多其他方法一样,实际上只是一对 看起来 类似于 [=92] 的方法=] 访问器。由于 Objective-C 将点符号转换为方法调用的方式,您以前从未注意到。不过,现在 Swift 更严格了——要获取和设置这个 "property,",您必须调用适当的方法。