无法从 Swift 代码访问 Objective-C 单例数组
Cannot access Objective-C singleton's array from Swift code
我在单例中创建了一个数组,以便从我的代码的多个部分向其中写入对象。方法如下:
// in singleton.h
#import <UIKit/UIKit.h>
// make globally accessible array
@interface MyManager : NSObject {
NSMutableArray *imgArray;
}
@property (nonatomic, retain) NSMutableArray *imgArray;
+ (id)sharedManager;
@end
// in singleton.m
#import "singleton.h"
对于我的 .m 文件:
@implementation MyManager
@synthesize imgArray;
#pragma mark Singleton Methods
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id) init {
if (self = [super init]) {
self.imgArray = [NSMutableArray new];
}
NSLog(@"initialized");
return self;
}
@end
我可以从我的 objective C 代码访问名为 imgArray 的数组。但是,在 swift 中,当我这样做时出现错误:
let array = MyManager.sharedManager()
array.imgArray.add("hello world") . (!!!) Value of type 'Any?' has no member 'imgArray'
我可以访问 MyManager.sharedManager()
,但为什么我不能像 objective C 一样访问 imgArray
?
将 + (id)sharedManager;
更改为 + (MyManager *)sharedManager;
。否则 Swift 不知道 sharedManager
是什么类型的对象,它会假设它是 Any
.
您应该将其声明为 instancetype
或 MyManager *
。例如
+ (MyManager *)sharedManager;
或
+ (instancetype)sharedManager;
一些建议:
单例的 Swift 约定是使用 shared
的 class 属性 名称,而不是 class 方法sharedManager()
。当你在 Objective-C 中声明它时,你可能想明确地说它是 class 属性:
@property (class, readonly, strong) MyManager *sharedManager NS_SWIFT_NAME(shared);
这不会改变 Objective-C 的任何行为,但在 Swift 中,您可以这样做:
let manager = MyManager.shared
manager.images.add(image)
这会产生更简洁和惯用的 Swift 代码。
我建议您审核 Objective-C 的可空性。即,确认什么可以 nil
什么不能。由于 imgArray
(我可能只称其为 images
)和 sharedManager
都不可能是 nil
,因此我只使用 NS_ASSUME_NONNULL_BEGIN
/END
告诉编译器“除非我另外告诉你,假设这个 属性 不能是 nil
”的宏:
// MyManager.h
@import UIKit;
NS_ASSUME_NONNULL_BEGIN
@interface MyManager : NSObject
@property (nonatomic, strong) NSMutableArray <UIImage *> *images;
@property (class, readonly, strong) MyManager *sharedManager NS_SWIFT_NAME(shared);
@end
NS_ASSUME_NONNULL_END
通过告诉编译器这两个不能是 nil
,这意味着您将不得不在 Swift 代码中减少不必要的可选项解包。
顺便说一句,请注意我没有声明实例变量。 (如果你确实需要一个,我不建议在 public 接口中声明它。)Objective-C 现在会自动为我们合成支持我们属性的 ivars。 (所以我的 属性 images
将有一个名为 _images
的 ivar 将为我合成。)而且你也不会 need/want @synthesize
行:
// MyManager.m
#import "MyManager.h"
@implementation MyManager
+ (instancetype)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (instancetype)init {
if (self = [super init]) {
self.images = [NSMutableArray new];
}
NSLog(@"initialized");
return self;
}
@end
我在单例中创建了一个数组,以便从我的代码的多个部分向其中写入对象。方法如下:
// in singleton.h
#import <UIKit/UIKit.h>
// make globally accessible array
@interface MyManager : NSObject {
NSMutableArray *imgArray;
}
@property (nonatomic, retain) NSMutableArray *imgArray;
+ (id)sharedManager;
@end
// in singleton.m
#import "singleton.h"
对于我的 .m 文件:
@implementation MyManager
@synthesize imgArray;
#pragma mark Singleton Methods
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id) init {
if (self = [super init]) {
self.imgArray = [NSMutableArray new];
}
NSLog(@"initialized");
return self;
}
@end
我可以从我的 objective C 代码访问名为 imgArray 的数组。但是,在 swift 中,当我这样做时出现错误:
let array = MyManager.sharedManager()
array.imgArray.add("hello world") . (!!!) Value of type 'Any?' has no member 'imgArray'
我可以访问 MyManager.sharedManager()
,但为什么我不能像 objective C 一样访问 imgArray
?
将 + (id)sharedManager;
更改为 + (MyManager *)sharedManager;
。否则 Swift 不知道 sharedManager
是什么类型的对象,它会假设它是 Any
.
您应该将其声明为 instancetype
或 MyManager *
。例如
+ (MyManager *)sharedManager;
或
+ (instancetype)sharedManager;
一些建议:
单例的 Swift 约定是使用
shared
的 class 属性 名称,而不是 class 方法sharedManager()
。当你在 Objective-C 中声明它时,你可能想明确地说它是 class 属性:@property (class, readonly, strong) MyManager *sharedManager NS_SWIFT_NAME(shared);
这不会改变 Objective-C 的任何行为,但在 Swift 中,您可以这样做:
let manager = MyManager.shared manager.images.add(image)
这会产生更简洁和惯用的 Swift 代码。
我建议您审核 Objective-C 的可空性。即,确认什么可以
nil
什么不能。由于imgArray
(我可能只称其为images
)和sharedManager
都不可能是nil
,因此我只使用NS_ASSUME_NONNULL_BEGIN
/END
告诉编译器“除非我另外告诉你,假设这个 属性 不能是nil
”的宏:// MyManager.h @import UIKit; NS_ASSUME_NONNULL_BEGIN @interface MyManager : NSObject @property (nonatomic, strong) NSMutableArray <UIImage *> *images; @property (class, readonly, strong) MyManager *sharedManager NS_SWIFT_NAME(shared); @end NS_ASSUME_NONNULL_END
通过告诉编译器这两个不能是
nil
,这意味着您将不得不在 Swift 代码中减少不必要的可选项解包。顺便说一句,请注意我没有声明实例变量。 (如果你确实需要一个,我不建议在 public 接口中声明它。)Objective-C 现在会自动为我们合成支持我们属性的 ivars。 (所以我的 属性
images
将有一个名为_images
的 ivar 将为我合成。)而且你也不会 need/want@synthesize
行:// MyManager.m #import "MyManager.h" @implementation MyManager + (instancetype)sharedManager { static MyManager *sharedMyManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedMyManager = [[self alloc] init]; }); return sharedMyManager; } - (instancetype)init { if (self = [super init]) { self.images = [NSMutableArray new]; } NSLog(@"initialized"); return self; } @end