无法从 Swift class 调用 Objective C class 委托

Unable to call an Objective C class delegate from a Swift class

我的问题是我需要 OldViewController.m 中的“protocolMethod”以委托方式从 NewViewController.swift 调用。

我正在处理的项目完全是用 Objective C 编写的,并且有一个新的视图控制器是用 Swift 编写的。

新的视图控制器应该调用委托方法,由 Objective C 调用者对象符合,因此 Objective C 视图控制器可以处理该调用。

应用程序运行并从 Swift 调用委托,但从未在 Objective C 视图控制器中实际执行。

我试过包含所有示例文件和应该调用的代码,所以这里是:

MyProtocol.h

#import <Foundation/Foundation.h>

@protocol MyProtocol <NSObject>

- (void)protocolMethod:(NSString*)input;

@end

我的桥接-Header.h

#ifndef My_Bridging_Header_h

#define My_Bridging_Header_h

#import <UIKit/UIKit.h>

#import "OldViewController.h"

#import "MyProtocol.h"

#endif

OldViewController.h

#import <UIKit/UIKit.h>

@interface OldViewController : UIViewController

@end

OldViewController.m

@interface OldViewController ()<MyProtocol>

@end

 
@implementation OldViewController

 
//THIS IS THE PROBLEM: NEVER GETS CALLED

- (void)protocolMethod:(NSString *)input {

    NSLog(@"protocolMethod:%@", input);

}

 

- (IBAction)myButtonClicked:(UIButton *)sender {

                NewViewController *newViewController =[self.storyboard instantiateViewControllerWithIdentifier:@"NewViewController"];

                [newViewController setModalTransitionStyle:UIModalTransitionStyleCoverVertical];

                [self presentViewController:newViewController animated:YES completion:nil];

 

}

@end

NewViewController.swift

import UIKit

class NewViewController: UIViewController {

    @objc weak var myProtocol: MyProtocol?

    override func viewWillAppear(_ animated: Bool) {

        self.myProtocol?.protocolMethod("testing 123")

    }

}

感谢您的帮助!

从 Swift

Objective-C class 中调用 objective-C 协议方法

在Objective-c中定义协议MyProtocol.h

#ifndef MyProtocol_h
#define MyProtocol_h
#import <Foundation/Foundation.h>

@protocol MyProtocol <NSObject>
@optional
- (void)protoMethod:(NSString *)input;
@end

#endif

定义LoginViewController.h

的接口
#import <UIKit/UIKit.h>
#import "MyProtocol.h"

@class NewViewController; //declare knowledge of swift class
@interface LoginViewController : UIViewController <MyProtocol>
// method to trigger testing manual
-(void)haveFun;
@end

定义 LoginViewController.m

的实现
#import "LoginViewController.h"
#import "YourProductModulName-Swift.h" // will bridge exposed swift class to objc

@implementation LoginViewController
-(void)protoMethod:(NSString*)input {
     NSLog(@"protocolMethod:%@", input);
}
- (void)haveFun {
    // did not use the storyboard to make testing simple
    // this is an @objc exposed swift class
    NewViewController *newViewController = [[NewViewController alloc] init];
    // now trigger predefined method that checks for protocol 
    [newViewController fun:self];
}
@end

现在让我们编写一个 swift class 子class NSObject,这里是 UIViewController 并将其暴露给 objc

import Foundation
import UIKit

@objc //expose class when you need to use it from Objective-C
class NewViewController: UIViewController {

    // as objc bridging is working with NSObjects,
    // we can use it instead of Any, which can't be exposed.
    @objc(foo) weak var foo : NSObject?
    
    override func viewWillAppear(_ animated: Bool) {
        // question was: how to call (id<MyProtocol>)-(void)protoMethod:
        // as we dont use storyboard for testing here..
        // nothing in here
    }
    
    // no autonaming, defined -(void)fun: instead
    @objc(fun:) func fun(protocolObj: MyProtocol) {
        let bar = protocolObj
        bar.protoMethod!("direct invokation of protoMethod")
        // ah why not, lets remember the object for later.
        foo = bar as? NSObject
        testme()
    }
    
    @objc func testme() {
        // as foo is NSObject here, check if exist
        if (foo != nil) {
            // cast foo and check for protocol
            if let loginview = foo as? MyProtocol {
                loginview.protoMethod!("PROTOCOL-LOL!")
            } else {
                print("i will allways love youuu!")
            }
        }
    }

}

现在让我们玩得开心并使用来回桥接的东西。 这将在 <MyProtocol> 之后分配 Objective-c class LoginViewController 并调用 -(void)haveFun 方法。此方法将分配一个 Swift Class NewViewController (重要!基于 NSObject),它将调用 @objc exposed swift func fun: 并给出 self作为必须遵循 MyProtocol 的参数。然后它将使用参数 NSString 调用 LoginViewController 的协议方法,并将 LoginViewController 对象存储在 weak var foo 中作为 NSObject。然后它将触发内部 swift testme() 并使用存储的 foo 再次检查它是否存在并符合协议 MyProtocol 并再次调用 protocolMethod -(void)protoMethod:(NSString*)string; 或如果不存在则打印一些东西符合。

LoginViewController *login = [[LoginViewController alloc] init];
[login haveFun];

不要忘记这里的示例需要 Swift 桥接到 Objective-C 和 Objective-C 桥接到 Swift。如果那是一个完美的设计模式,那就另当别论了。