如何在swift扩展中实现objective-C类的objective-C委托函数



我正试图通过对Objective-C类的快速扩展来符合该类上的Objective-C委托方法。问题是,在下面的swift扩展中定义此函数的主体时,我没有自动完成选项。我不得不从Objective-C手动翻译它,但它仍然不起作用。。我知道委托的设置是正确的,因为当我直接在ObjectiveCConformingClass中提供委托函数体时,它工作得很好(当我编写函数时会自动完成(。

我有一个像这样的快速类(我想我需要解决的问题(:

extension ObjectiveCConformingClass {
func delegateFunction(with index: Int, viewName: String, action: String, dictionary: [String : Any]) {
//Never gets called.
}
}

扩展这样的类:

符合委托的类:

@interface ObjectiveCConformingClass : SuperClass <ObjectiveCDelegate>
//Whatever
@end

代表:

@protocol ObjectiveCDelegate <NSObject>
@optional
- (void)delegateFunction:(NSInteger)index
view:(nonnull NSString *)view
action:(nonnull NSString *)action
dictionary:(nonnull NSDictionary<NSString *, id> *)dictionary;
@end

总结一下:我需要在类的快速扩展中遵循这个委托,而不是实际的类。如果我直接在objective-C类中这样做,效果会很好。有什么想法为什么它不起作用吗?或者这是否可能?

以下是一些相当相似的问题,它们要求不同的东西,所以对我没有帮助。(即这是而不是重复的线程(

  • 在Swift中实现ObjectiveC委托
  • Objective-C协议的Swift扩展
  • 在swift中使用objective-c编写的委托方法
  • 在Swift中使用扩展实现委托函数

阅读时请慢慢来
将代表视为id<ProtocolName>"指向另一个对象的指针">符合协议。

@protocol ObjectiveCDelegate <NSObject>
@optional
- (void)delegateMethod:(NSInteger)index
view:(nonnull NSString *)view
action:(nonnull NSString *)action
dictionary:(nonnull NSDictionary<NSString *, id> *)dictionary;
@end

通常,想要使用委托的@interface ClassName : NSObject应该有一个属性来保留它或将其设置为nil(可为null(,这意味着为什么您希望它

@property (nonatomic, weak) id<ObjectiveCDelegate> delegate;

而将成为您的委托的类(对象(必须符合此协议,因此您必须像以前一样在其接口中声明此协议。美得像。。

@interface ObjectiveCConformingClass : SuperClass <ObjectiveCDelegate>
@property (nonatomic, weak) id<ObjectiveCDelegate> delegate;
-(void)invokeDelegate; //for testing.
@end

因为上面的协议有可选的方法声明,所以当你没有实现它时,它不会抛出警告。为了避免在使用ClassName(对象(的类中处理委托时遇到问题,你需要检查委托属性是否不是nil,并且是否可以响应所需的方法名。

@implementation ObjectiveCConformingClass
-(void)delegateMethod:(NSInteger)index view:(NSString *)view action:(NSString *)action dictionary:(NSDictionary<NSString *,id> *)dictionary {
NSLog(@"original objc delegateMethod, called from %@", view);
}
-(void)invokeDelegate {
if (_delegate) {
// you can double check if the delegate is really an id<ProtocolName>
if ([_delegate conformsToProtocol:@protocol(ObjectiveCDelegate)]) {
// well you don't know if delegateMethod was implemented, it was optional
// so you have to check, 
// indeed it's implemented above, but it is safe this way.
if ([_delegate respondsToSelector:@selector(delegateMethod:view:action:dictionary:)]) {
//now you can call it safely
[_delegate delegateMethod:0 view:@"original ObjectiveCConformingClass" action:@"a" dictionary:@{@"key":@"value"}];
}
}
} else {
NSLog(@"original ObjectiveCConformingClass delegate is nil");
}
}
@end

到目前为止,它在objective-c 中工作

现在在swift中,您甚至可以在扩展中使用委托

extension ObjectiveCConformingClass  {

func extensionMethod() {
if ((delegate) != nil) {
if ((delegate?.responds(to: #selector(delegateMethod(_:view:action:dictionary:))))!) {
delegate?.delegateMethod?(1,view: "extension ObjectiveCConformingClass",action: "world",dictionary: ["foo":"bar"])
}
} else {
print("extension ObjectiveCConformingClass: delegate is nil")
}
}

// following will make you extreme trouble..
// see the missing _ so this is a different method then the objc variant
// its selector is #selector(delegateMethod(index:view:action:dictionary:)
func delegateMethod(index: Int, view: String, action: String, dictionary: [String : Any]) {
print("swift extension func delegateMethod, called from",view)
}
// #selector() is heavily confused what method to select when uncommented
// because selector is #selector(delegateMethod(_:view:action:dictionary:)
// which is declared in objc and can not be directly extended in swift
//func delegateMethod(_ index: Int, view: String, action: String, dictionary: [String : Any]) {
//    print("swift extension func delegateMethod, called from",view)
//}
}

让我们检查子类化时swift扩展是否正常工作。

class ClassOtherName : ObjectiveCConformingClass {
func subclassMethod() {
if (delegate != nil) {
// you still don't know if the method was implemented, so check
if ((delegate?.responds(to: #selector(delegateMethod(_:view:action:dictionary:))))!) {
delegate?.delegateMethod?(1, view:"subclass ClassOtherName", action: "action", dictionary: ["key" : "value"])
} else {
print("delegate seems not conforming to protocol")
}
} else {
print("subclass ClassOtherName delegate is nil")
}
}
// of course you can override in subclasses, even if this was a super protocol method
// see the difference.. _ as argument used here
// because Overriding non-@objc declarations from extensions is not supported
override func delegateMethod(_ index: Int, view: String, action: String, dictionary: [String : Any]) {
print("override func delegateMethod, called from",view)
}
}

让我们测试

let a = ObjectiveCConformingClass() //extended version
a.extensionMethod()  // extension ObjectiveCConformingClass: delegate is nil
//a.subclassMethod() // does not exist in ObjectiveCConformingClass
a.invokeDelegate()   // original ObjectiveCConformingClass delegate is nil

let o = ClassOtherName()  // subclassed version of extension
o.delegate = a
o.extensionMethod()  // original objc delegateMethod, called from extension ObjectiveCConformingClass
o.subclassMethod()   // original objc delegateMethod, called from subclass ClassOtherName
o.invokeDelegate()   // original objc delegateMethod, called from original ObjectiveCConformingClass

o.delegate = nil
o.extensionMethod()  // extension ObjectiveCConformingClass: delegate is nil
o.subclassMethod()   // subclass ClassOtherName delegate is nil
o.invokeDelegate()   // original ObjectiveCConformingClass delegate is nil

o.delegate = o //aka o == self
o.extensionMethod()  // override func delegateMethod, called from extension ObjectiveCConformingClass
o.subclassMethod()   // override func delegateMethod, called from subclass ClassOtherName
o.invokeDelegate()   // override func delegateMethod, called from original ObjectiveCConformingClass

希望这不会太令人困惑,但你可以看到谁在呼唤谁,被召唤的是什么。

相关内容

  • 没有找到相关文章

最新更新