如何解决从Objective C到Swift分享单身人士
我试图从Swift访问Objective C单例,但是我似乎只在单例的init函数中获得了初始值。公开的flightControllerState对象在委托函数中已更新,我可以看到在Objective C端该值已正确更新。
我在SO上关注了一些不同的帖子,在article中也关注了如何从Swift调用共享对象。 (我还应该提到,这是否可能在React Native项目中运行?)
EDIT 更新了快速代码-我在init方法中添加了错误的行以获取共享实例-问题仍然相同
Objective-C Singleton
@import DJISDK;
@interface RCTBridgeDJIFlightController : RCTEventEmitter<DJIFlightControllerDelegate> {
DJIFlightControllerState *flightControllerState;
}
@property(nonatomic,readonly) DJIFlightControllerState *flightControllerState;
+ (id)sharedFlightController;
@end
@implementation RCTBridgeDJIFlightController
DJIFlightControllerState *flightControllerState;
@synthesize flightControllerState;
+ (id)sharedFlightController {
static RCTBridgeDJIFlightController *sharedFlightControllerInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
sharedFlightControllerInstance = [[self alloc] init];
});
return sharedFlightControllerInstance;
}
- (id)init {
// I also tried this to make sure the shared instance was returned but no luck
//if (sharedFlightControllerInstance != nil) {
// return sharedFlightControllerInstance;
//}
if (self = [super init]) {
flightControllerState = nil;
}
return self;
}
-(void)flightController:(DJIFlightController *)fc didUpdateState:(DJIFlightControllerState *)state {
flightControllerState = state;
}
@end
Swift类调用单例并访问值
class VirtualStickController {
var flightControllerSharedInstance: RCTBridgeDJIFlightController
override init() {
self.flightControllerSharedInstance = RCTBridgeDJIFlightController.sharedFlightController()
}
func getFlightControllerState() {
if let state = flightControllerSharedInstance.flightControllerState {
print("FLIGHT CONTROLLER STATE: \(state)") // always null
} else {
print ("NULL")
}
}
解决方法
DJIFlightControllerState *flightControllerState; @synthesize flightControllerState;
(现代)Objective-C的属性无需使用@synthesize
,除非有特殊情况。
属性flightControllerState
是一个实例属性,将使用隐藏的 instance 变量(用于存储)来合成(带有或不带有@synthesize
)。
变量flightControllerState
是一个 global 变量,它恰好与该属性具有相同的名称,但与该属性没有任何联系。
猜测是您要在Objective-C中更改全局变量,并期望通过属性在Swift中看到结果,
>删除全局变量,然后检查其余代码。
除此之外,您的代码还会生成有效的共享实例,可以在Objective-C和Swift之间共享该实例,而用另一种语言进行的更改将在另一种语言中可见。
HTH
,关于关于如何从Swift访问Objective C单例的名义问题,我建议使用替代方法。现代惯例是将sharedFlightController
声明为class
属性,并将init
声明为NS_UNAVAILABLE
:
@interface RCTBridgeDJIFlightController : NSObject
...
@property (nonatomic,readonly,class) RCTBridgeDJIFlightController *sharedFlightController;
- (instancetype)init NS_UNAVAILABLE;
@end
该实现将为此类属性实现一个吸气剂:
@implementation RCTBridgeDJIFlightController
+ (instancetype)sharedFlightController {
static RCTBridgeDJIFlightController *sharedFlightControllerInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
sharedFlightControllerInstance = [[self alloc] init];
});
return sharedFlightControllerInstance;
}
...
@end
现在,您的Swift代码可以引用RCTBridgeDJIFlightController.shared
,与Swift单例的惯例一样。
关于您为什么会收到nil
的状态的问题,可能有两个问题之一:
-
您的Objective-C代码将显式定义的ivars,手动综合和全局变量混淆在一起。 (请参见下文。)
-
我还建议您确认
flightController:didUpdateState:
是否曾经被打过。 (我看不到您曾经设置过飞行控制器的委托人。)在该方法中添加一个断点或NSLog
语句并确认。
关于上面的第一个问题,我建议:
-
您不应在
init
方法中使用这些注释行。如果要确保使用单例对象,则将init
声明为NS_UNAVAILABLE
。 -
鉴于您的所有
init
方法正在将flightControllerState
更新为nil
,您可以将其完全删除。在ARC中,属性会为您初始化为nil
。 -
您不应在
@interface
中声明显式ivar。让编译器自动为您合成。 -
您不应该
@synthesize
中的ivar@implementation
。编译器现在将自动为您合成(并将为ivar使用适当的名称,并在属性名称下添加下划线。 -
您不应在
@implementation
中声明该全局变量。 -
如果要在Swift中使用此
sharedFlightController
,则应将其定义为class
属性,而不是类方法。我知道that article建议使用类方法,但这实际上不是最佳实践。
因此:
// RCTBridgeDJIFlightController.h
#import <Foundation/Foundation.h>
// dji imports here
NS_ASSUME_NONNULL_BEGIN
@interface RCTBridgeDJIFlightController : NSObject
@property (nonatomic,nullable) DJIFlightControllerState *flightControllerState;
@property (nonatomic,class) RCTBridgeDJIFlightController *sharedFlightController;
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END
和
// RCTBridgeDJIFlightController.m
#import "RCTBridgeDJIFlightController.h"
#import "RCTBridgeDJIFlightController.h"
@interface RCTBridgeDJIFlightController ()
@property (nonatomic,nullable) DJIFlightControllerState *flightControllerState;
@end
@implementation RCTBridgeDJIFlightController
+ (instancetype)sharedFlightController {
static RCTBridgeDJIFlightController *sharedFlightControllerInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
sharedFlightControllerInstance = [[self alloc] init];
});
return sharedFlightControllerInstance;
}
- (void)flightController:(DJIFlightController *)fc didUpdateState:(DJIFlightControllerState *)state {
NSLog(@"State updated");
self.flightControllerState = state;
}
@end
最终结果是您现在可以像这样使用它:
class VirtualStickController {
func getFlightControllerState() {
if let state = RCTBridgeDJIFlightController.shared.flightControllerState {
print("FLIGHT CONTROLLER STATE: \(state)") // always null
} else {
print("NULL")
}
}
}
请注意,由于sharedFlightController
现在是一个类属性,因此Swift / ObjC互操作性足够智能,因此Swift代码可以仅引用shared
,如上所示。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。