我之前曾询问过如何使用可选方法创建协议的问题。几乎使用Objective-c的反应。见here。
我做了,一切正常,因为我正在使用
var delegate: SessionDelegate?;
也就是说,“delegate”是一个可选的SessionDelegate。为了从该委托调用方法,我可以简单地写:
self.delegate?.willOpenSession?(self);
哪个好。但是,然后我,为什么让代表可选?所以我改变了它:
var delegate: SessionDelegate;
显然,电话也会改变:
self.delegate.willOpenSession?(self);
问题是,最后一行(以及任何其他类型)说:'SessionDelegate'没有名为'willOpenSession'的成员。为什么这不起作用?
这是我的代码:
SessionDelegate.h
@class Session;
@protocol SessionDelegate <NSObject>
@optional
- (BOOL)willOpenSession:(Session*)session;
- (void)didOpenSession:(Session*)session;
- (void)didFailOpenningSession:(Session*)session withError:(NSError*)error;
- (BOOL)willCloseSession:(Session*)session destroyingToken:(BOOL)destroyingToken;
- (void)didCloseSession:(Session*)session destroyingToken:(BOOL)destroyingToken;
@end
XXX-桥接-Header.h
#import <Foundation/Foundation.h>
#import <FacebookSDK/FacebookSDK.h>
#import "SessionDelegate.h"
Session.swift
import Foundation
protocol Session {
var delegate: SessionDelegate { get set };
var isOpen: Bool { get };
var isCached: Bool { get };
func open();
func close();
func destroy();
}
FacebookSession.swift
import Foundation
class FacebookSession : Session {
var delegate: SessionDelegate;
var isOpen: Bool {
get {
return FBSession.activeSession().isOpen;
}
}
// TODO
var isCached: Bool {
get {
return false;
}
}
init(delegate: SessionDelegate) {
self.delegate = delegate;
}
func open() {
if self.isOpen {
return;
}
// Trigger the "will" event
self.delegate.willOpenSession?(self);
// Handle session state changes
var completionHandler: FBSessionStateHandler = {
session, status, error in
if error {
// Login failed for some reason, so we notify the delegate.
// TODO we should turn this NSError message into something more generic (that is, not facebook specific)
self.delegate.didFailOpenningSession?(self, withError: error);
}
else if status.value == FBSessionStateClosedLoginFailed.value {
// Login failed with no error. I'm not sure this ever happens
self.delegate.didFailOpenningSession?(self, withError: error);
}
else if status.value == FBSessionStateOpen.value || status.value == FBSessionStateOpenTokenExtended.value {
// Session is now open, we should notify the delegate
self.delegate.didOpenSession?(self);
}
else {
// There's no error but the session didn't open either. I don't think this ever happens, but if it does, what should we do here?
abort();
}
};
// Open the session, prompting the user if necessary
if FBSession.openActiveSessionWithReadPermissions([], allowLoginUI: true, completionHandler: completionHandler) {
// If we end up here, the session token must exist, se we now have an open session
self.delegate.d didOpenSession?(self);
}
}
func close() {
}
func destroy() {
}
}
最好的问候。
编辑:我也尝试了以下
self.delegate.willOpenSession?(self as Session);
和
self.delegate.willOpenSession(self as Session);
都没有效果。
编辑:毕竟,如果我使用
,它就不起作用var delegate: SessionDelegate?;
编辑:上一次更改也会更改错误消息。现在我有可选的SessionDelegate(正如我在上一个编辑中所说)和以下行
self.delegate?.willOpenSession?(self)
说:“找不到会员'willOpenSession'”
答案 0 :(得分:1)
您收到此错误是因为您将Session
定义为协议,但SessionDelegate
协议中的Objective-C方法定义需要Session
类或子类。在Swift中,您可以在方法定义中将协议名称与类名互换使用,但在Objective-C中存在差异:
- (void)willOpenSession:(Session *)session; // expects instance of Session class or subclass
- (void)willOpenSession:(id<Session>)session; // expects object conforming to Session protocol
根据您发布的代码,我无法说明为什么您已将Session
声明为协议 - 它是否为不同的类添加了功能?它可能是一个超级类FacebookSession
(可能是其他会话)只是继承自?将Session
更改为类(以及存根方法)可以解决问题。否则,您需要更改SessionDelegate
方法以期望id<Session>
,但对我来说,这会破坏编译器。