[英]How to implement a swift delegate method in objective-C having parameter?
[英]How to implement an objective-C delegate function of an objective-C class in a swift extension
我正在嘗試通過該類上的 swift 擴展來符合 Objective-C 類上的 Objective-C 委托方法。 問題是在下面的 swift 擴展中定義此函數的主體時,我沒有自動完成選項。 我不得不從 Objective-C 手動翻譯它,但它仍然不起作用。. )。
我有一個這樣的快速課程(我想我需要修復什么):
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 類中執行它,它工作正常。 任何想法為什么它不起作用? 或者,如果這甚至可能?
這里有一些相當相似的問題,它們要求不同的東西,所以對我沒有幫助。 (即這不是重復的線程)
看書的時候抓緊時間。。
將委托視為符合協議的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
(可空),這意味着你為什么想要它weak 。
@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中工作
現在,即使在擴展中,您也可以迅速使用委托
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
希望這不會太令人困惑,但您會看到誰在調用誰以及調用了什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.