objective-c - 斯威夫特:@objc(...) 属性
问题描述
在 Apple 生成的代码(NSManagedObject
例如,Core Data 子类)中,我看到了这一点:
@objc(LPFile)
public class LPFile: NSManagedObject {
...
}
我的问题是:为什么@objc
要按上述方式进行声明,而不是:
@objc public class LPFile: NSManagedObject {
...
}
或者
@objcMembers public class LPFile: NSManagedObject {
...
}
@objc(identifier)
单独申报有什么特别之处?我似乎找不到关于它的文档,而谷歌搜索只是发现了其他两种方法。谢谢。
(注意:我知道类前缀不是惯用的 Swift。)
解决方案
@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 框架 ( NS
, UI
, CF
, ...) 中的这两个字母前缀和 3rd 方代码中的三个字母前缀的原因。一些第 3 方开发人员仍然使用两个字母,但这是另一回事。
Swift 有更多的命名空间——它们基于模块。当使用 pure@objc
属性时,包含模块名称是一个安全的选择。避免可能的歧义。
例如检查NSEntityDescription
类 -managedObjectClassName
属性:
表示接收者实体的类的名称。
有很多东西利用了 Objective-C 运行时特性,很多东西只是基于名称(字符串),......
推荐阅读
- python - 使用用户输入作为分配数据脚本的最小值和最大值
- git - 在 Git 中创建分支时恢复已删除的文件
- azure-ad-b2c - 您可以根据协议有条件地“SendClaims”吗?
- ios - Flutter ios 错误:ios/Runner/GeneratedPluginRegistrant:使用未声明的标识符“声音”
- powershell - 如何使用 PowerShell 复制文件并创建包含该文件的目录?
- c++ - 如何制作一个将函数包装在 noexcept 可检测、可调用对象中的类模板,以用作 std::unique_ptr 自定义删除器?
- javascript - 给定Javascript中的评估条件,如何返回数组的第一个元素?
- javascript - chartjs 3.0 中的 generateLegend() 发生了什么?
- types - 什么时候只有在运行时才知道类型?
- android - Android 动态功能是否与应用共享类路径?