Swift:@objc(...)属性

在Apple生成的代码中(例如,核心数据NSManagedObject子类),我看到了这一点:

@objc(LPFile)
public class LPFile: NSManagedObject {
   ...
}

我的问题是:为什么@objc声明如上所述而不是:

@objc public class LPFile: NSManagedObject {
   ...
}

@objcMembers public class LPFile: NSManagedObject {
   ...
}

单独的@objc(identifier)声明有何特别之处?我似乎找不到关于它的文档,而Google搜索只是出现了另外两种方法。谢谢。

(注意:我知道类前缀不是惯用的Swift。)

iCMS 回答:Swift:@objc(...)属性

@Alladinian是正确的。假设您有一个包含两个类的框架SharedSwift

@objc public class Foo: NSObject {}
@objc(Bar) public class Bar: NSObject {}

您可以在Objective-C代码中导入该框架并直接使用这两个类:

@import SharedSwift;

Bar *b = [[Bar alloc] init];
Foo *f = [[Foo alloc] init];

但是因为Objective-C具有强大的运行时,所以您可以做很多魔术。一个示例是NSClassFromString函数:

- (id _Nullable)instanceByName:(NSString * _Nonnull)name {
    Class c = NSClassFromString(name);
    return [[c alloc] init];
}

Foo *foo = [self instanceByName:@"Foo"];
Bar *bar = [self instanceByName:@"Bar"];
    
NSLog(@"%@ %@",foo,bar);

输出为:

(null) <Bar: 0x6000015c4200>

出什么问题了? className ...

NSLog(@"%@ %@",[Foo className],[Bar className]);

...在一种情况下(SharedSwift.Foo返回@objc,在另一种情况下返回Bar@objc(Bar))。

SharedSwift.Foo Bar

让我们将AnotherSwift框架添加到具有相同类的组合中,并尝试同时使用两者中的Foo

@import SharedSwift;

NSLog(@"%@",[Foo className]); // SharedSwift.Foo
@import AnotherSwift;

NSLog(@"%@",[Foo className]); // AnotherSwift.Foo

工作正常。使用Bar类尝试相同的事情:

@import SharedSwift;

NSLog(@"%@",[Bar className]); // Bar
@import AnotherSwift;

NSLog(@"%@",[Bar className]); // Bar
在两个框架中都定义了

Bar类,并且未定义使用哪个类。尝试执行此操作时,请在控制台中看到错误:

Class Bar is implemented in both
.../Debug/SharedSwift.framework/Versions/A/SharedSwift (0x102b931c0) and
.../Debug/AnotherSwift.framework/Versions/A/AnotherSwift (0x102b841c0).
One of the two will be used. Which one is undefined.

这是什么原因?

如您所见,Objective-C代码(@import SharedSwift和直接使用Foo)与Objective-C运行时名称(NSClassFromString,...)之间是有区别的。

Objective-C世界中的所有内容都有一个名称空间。这就是Apple框架中这两个字母前缀(NSUICF,...)和第三方代码中三个字母前缀的原因。一些第三方开发人员仍然使用两个字母,但这是另一回事。

Swift具有更多的命名空间-它们基于模块。使用纯@objc属性时,最好包含模块名称。为了避免可能的歧义。

例如,检查NSEntityDescription类-managedObjectClassName属性:

代表接收者实体的类的名称。

有很多东西可以利用Objective-C运行时功能,很多东西只是基于名称(字符串),...

本文链接:https://www.f2er.com/1890576.html

大家都在问