@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 拥有强大的运行时,你可以做很多事情magic。一个例子是NSClassFromString https://developer.apple.com/documentation/foundation/1395135-nsclassfromstring?language=objc功能:
- (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
) and Bar
在另一张(@objc(Bar)
).
SharedSwift.Foo Bar
让我们添加AnotherSwift
框架与相同的类混合并尝试使用Foo
来自两者:
@import SharedSwift;
NSLog(@"%@", [Foo className]); // SharedSwift.Foo
@import AnotherSwift;
NSLog(@"%@", [Foo className]); // AnotherSwift.Foo
按预期工作。尝试同样的事情Bar
class:
@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
, ...) 和第 3 方代码中的三个字母前缀。一些第三方开发人员仍然使用两个字母,但那是另一回事了。
Swift 有更多的命名空间——它们基于模块。当纯粹的情况下,包含模块名称是一个安全的选择@objc
使用属性。以避免可能出现的歧义。
检查NSEntityDescription https://developer.apple.com/documentation/coredata/nsentitydescription?language=objc类例如 -managedObjectClassName https://developer.apple.com/documentation/coredata/nsentitydescription/1425131-managedobjectclassname?language=objc财产:
代表接收者实体的类的名称。
有很多东西可以利用 Objective-C 运行时特性,很多东西只是基于名称(字符串),...