簡體   English   中英

如何在 swift 擴展中實現 Objective-C 類的 Objective-C 委托函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM