gpt4 book ai didi

objective-c - 如何在Swift中调用Objective C类方法

转载 作者:行者123 更新时间:2023-11-28 09:01:52 25 4
gpt4 key购买 nike

在Objective-C头上,我有以下类方法声明:

@interface WXMediaMessage : NSObject

+(WXMediaMessage *) message;

我尝试按如下方式调用此方法:
var message : WXMediaMessage = WXMediaMessage.message()

但没用。我已经设置了桥接头。
编辑:
如果我如前所述调用方法,它将显示一个错误 'message()' is unavailable: use object construction 'WXMediaMessage()'
如果使用WXmediaMessage(),则错误不会消失。但是,如果在目标C中调用它,它是否会返回与[WXMediaMessage message]相同的结果?
MYAPP_bridgeting_头.h
#ifndef MYAPP_bridging_header_h
#define MYAPP_bridging_header_h

#import "WXApi.h"
#import "WXApiObject.h"

#endif

WXApiObject.h代码段
@interface WXMediaMessage : NSObject

+(WXMediaMessage *) message;

@end

WXApiObject.m文件
(It is an external api, so I can't see the content)

最佳答案

I mean: BUT WHY?
这就是我们要问的。马特的回答是正确的,因为重命名方法可以解决问题,但我们仍然要问为什么。
答案是因为Swift实际上将方便的方法重新映射到构造函数。
所以当我们在Objective-C中调用这样的方法时:

[WXMediaMessage message];

在Swift中,我们应该只调用 WXMediaMessage()。在Objective-C中,这相当于调用:
[[WXMediaMessage alloc] init];

需要注意的是,当我们使用Swift默认初始值设定项时,实际的工厂方法不会被调用。这将直接转到 init而不调用工厂包装器。但最佳实践建议我们的工厂方法应该是 [[self alloc] init];。一个值得注意的建议可能是使用singleton,但是如果我们使用singleton工厂方法,我们应该遵循Apple设置的模式,并使用“shared”前缀命名工厂方法:
+ (instancetype)sharedMessage;

以下Swift代码将完全有效:
let message = WXMediaMessage.sharedMessage()

但如果 message不是单例,那么它应该不超过 return [[self alloc] init];,这就是我们使用以下Swift代码得到的结果:
let message = WXMediaMessage()

这就是错误信息告诉我们要做的:
'message()' is unavailable: use object construction 'WXMediaMessage()'

错误消息告诉我们使用默认的Swift初始值设定项,而不是Objective-C工厂方法。这是有道理的。任何人想要Objective-C中的工厂方法的唯一原因是 [[MyClass alloc] init]看起来很难看。我们所有的初始化仍然应该在 init方法中完成,但是。。。不是在我们创建的工厂方法中,因为我们不希望看到 alloc] init]。。。
考虑以下目标C类:
@interface FooBar : NSObject

+ (instancetype)fooBar;

- (void)test;

@end

@implementation FooBar

- (instancetype)init {
self = [super init];
if (self) {
NSLog(@"initialized");
}
return self;
}

+ (instancetype)fooBar {
NSLog(@"initialized with fooBar");
return [[self alloc] init];
}

- (void)test {
NSLog(@"Testing FooBar");
}

@end

现在使用以下Swift代码:
let var1 = FooBar()
var1.test()

我们得到以下输出:
2014-11-08 10:48:30.980 FooBar[5539:279057] initialized
2014-11-08 10:48:30.981 FooBar[5539:279057] Testing FooBar

如我们所见,方法 fooBar从未被调用。但事实上,如果您在正确地构建Objective-C类时考虑到良好的实践,那么命名为Objective-C类的类方法不应超过:
return [[self alloc] init];

你的方法应该处理所有的设置。
当我们使用不那么简单的初始化器和工厂方法时,发生的事情变得更加明显。
考虑一下,如果我们添加一种用数字初始化类的方法:
@interface FooBar : NSObject

+ (instancetype)fooBarWithNumber:(int)number;
- (void)test;

@end

@implementation FooBar {
int _number;
}

- (instancetype)init {
self = [super init];
if (self) {
NSLog(@"initialized");
}
return self;
}

- (instancetype)initWithNumber:(int)number {
self = [self init];
if (self) {
NSLog(@"init with number: %i", number);
_number = number;
}
return self;
}

+ (instancetype)fooBarWithNumber:(int)number {
NSLog(@"fooBar with number: %i", number);
return [[self alloc] initWithNumber:number];
}

- (void)test {
NSLog(@"Testing FooBar (number: %i)", _number);
}

@end

在这一点上,注意我们的 init公开了 .h方法,而不是 fooBarWithNumber:方法。
现在让我们回到Swift代码:
let var1 = FooBar(number: 3)
var1.test()

Swift已将我们的 initWithNumber:方法转换为初始值设定项: fooBarWithNumber:
结果如下:
2014-11-08 10:57:01.894 FooBar[5603:282864] fooBar with number: 3
2014-11-08 10:57:01.894 FooBar[5603:282864] initialized
2014-11-08 10:57:01.895 FooBar[5603:282864] init with number: 3
2014-11-08 10:57:01.895 FooBar[5603:282864] Testing FooBar (number: 3)

我们的 FooBar(number:Int32)方法被调用,它调用 fooBarWithNumber:,它调用 initWithNumber:
所以,“为什么”这个问题的答案是因为Swift将Objective-C初始值设定项和工厂方法转换为Swift样式的初始值设定项。
要进一步展开,问题甚至不仅仅在于方法名本身。它是方法名、类名和返回类型的组合。这里,我们使用 init作为返回类型。如果我们使用 instancetype或特定的类类型,就会遇到问题。但请考虑:
@interface FooBar

+ (NSArray *)fooBar;

@end

并假定该类方法的某些有效实现与类名匹配,但返回类型与我们的类不匹配。
现在,以下方法是完全有效的Swift代码:
let fooBarArray = FooBar.fooBar()

由于返回类型与类不匹配,Swift无法将其转换为类初始值设定项,因此我们的方法很好。
值得注意的是,如果我们选择 instancetype作为方法的返回类型,那么:
+ (id)fooBar;

斯威夫特会让我们逃脱的。。。但它会警告我们,我们的变量被推断为具有类型“AnyObject!”建议我们添加一个显式类型,因此建议:
let var1: FooBar = FooBar.fooBar()

它会让我们这样做。。。但最佳实践几乎肯定建议不要使用 id作为返回类型。苹果最近几乎把所有的 id返回类型都改成了 id

关于objective-c - 如何在Swift中调用Objective C类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31785039/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com