无法从 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。如果那是一个完美的设计模式,那就另当别论了。
我的问题是我需要 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。如果那是一个完美的设计模式,那就另当别论了。