简体   繁体   English

无法从 Swift ZA2F2ED4F8EBC2CBB4C21A29DC40AB6DZ 调用目标 C class 代表

[英]Unable to call an Objective C class delegate from a Swift class

My issue here is that I need the "protocolMethod" in the OldViewController.m to be called from the NewViewController.swift in a delegate fashion.我的问题是我需要以委托方式从 NewViewController.swift 调用 OldViewController.m 中的“protocolMethod”。

The project I'm working on was completely written in Objective C, and there's a new View Controller that was written in Swift.我正在做的项目完全是用Objective C编写的,还有一个用Swift编写的新视图Controller。

The new View Controller is supposed to call a delegate method, conformed by the Objective C caller object, so the Objective C View Controller can process that call. The new View Controller is supposed to call a delegate method, conformed by the Objective C caller object, so the Objective C View Controller can process that call.

The app runs and the delegate is called from Swift, but never actually executed in the Objective C View Controller.应用程序运行并从 Swift 调用委托,但从未在目标 C 视图 Controller 中实际执行。

I've tried including all the sample files and the code that's supposed to be called, so here it is:我已经尝试包含所有示例文件和应该调用的代码,所以这里是:

MyProtocol.h我的协议.h

#import <Foundation/Foundation.h>

@protocol MyProtocol <NSObject>

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

@end

My-Bridging-Header.h我的桥接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 OldViewController.h

#import <UIKit/UIKit.h>

@interface OldViewController : UIViewController

@end

OldViewController.m旧视图控制器.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 NewViewController.swift

import UIKit

class NewViewController: UIViewController {

    @objc weak var myProtocol: MyProtocol?

    override func viewWillAppear(_ animated: Bool) {

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

    }

}

Thank you for your help!谢谢您的帮助!

Call a objective-C protocol method in Objective-C class from Swift调用 Objective-C class 中的objective-C协议方法从 ZAE832E9B5BDA2699DB45F3FA6AA8C556

define the protocol in Objective-c MyProtocol.h在 Objective-c MyProtocol.h中定义协议

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

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

#endif

define interface of LoginViewController.h定义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

define implementation of LoginViewController.m定义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

now let us write a swift class that is subclassing an NSObject, here UIViewController and expose it to objc现在让我们编写一个 swift 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!")
            }
        }
    }

}

now lets have some fun and use the back and forth bridged stuff.现在让我们玩得开心,并使用来回桥接的东西。 This will allocate a Objective-c class LoginViewController following <MyProtocol> and invoke -(void)haveFun method.这将在<MyProtocol>之后分配一个 Objective-c class LoginViewController并调用-(void)haveFun方法。 This method will allocate a Swift Class NewViewController (important! based on NSObject) that will invoke @objc exposed swift func fun: and give self as parameter that must follow the MyProtocol.此方法将分配一个 Swift Class NewViewController (重要!基于 NSObject),它将调用 @objc 暴露的self func fun:并给出 my 作为必须遵循的参数。 It will then invoke the protocol method of LoginViewController with a parameter NSString and store the LoginViewController object in weak var foo as NSObject .然后它将使用参数NSString调用 LoginViewController 的协议方法,并将 LoginViewController object 作为NSObject存储在weak var foo中。 Then it will trigger internal swift testme() and use the stored foo to check again if it exists and conforms to protocol MyProtocol and invokes the protocolMethod -(void)protoMethod:(NSString*)string;然后它将触发内部 swift testme()并使用存储的foo再次检查它是否存在并符合协议 MyProtocol 并调用 protocolMethod -(void)protoMethod:(NSString*)string; again or print something if not conforming.再次打印或打印不符合要求的内容。

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

Don't forget the example here needs Swift bridging to Objective-C and Objective-C bridging to Swift.不要忘记这里的示例需要 Swift 桥接到 Objective-C 和 Objective-C 桥接到 ZAE832E9B5BDA26996ZDB4。 If that is a perfect design pattern is another talk.如果这是一个完美的设计模式,那就另当别论了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM