Swift: @objc(...) 属性
Swift: @objc(...) Attribute
在 Apple 生成的代码中(例如,Core Data NSManagedObject
subclasses)我看到了这个:
@objc(LPFile)
public class LPFile: NSManagedObject {
...
}
我的问题是: 为什么 @objc
声明如上,而不是:
@objc public class LPFile: NSManagedObject {
...
}
或
@objcMembers public class LPFile: NSManagedObject {
...
}
单独的 @objc(identifier)
声明有什么特别之处?我似乎无法找到关于它的文档,谷歌搜索只会出现其他两种方法。谢谢。
(注意:我知道 class 前缀不是惯用的 Swift。)
@Alladinian 是对的。假设你有一个框架 SharedSwift
有两个 classes:
@objc public class Foo: NSObject {}
@objc(Bar) public class Bar: NSObject {}
你可以在Objective-C代码中引入这个框架,直接使用这两个class:
@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]);
... returns SharedSwift.Foo
在一种情况下 (@objc
) 和 Bar
在另一种情况下 (@objc(Bar)
).
SharedSwift.Foo Bar
让我们将 AnotherSwift
框架添加到具有相同 classes 的组合中,并尝试使用来自两者的 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 在两个框架中都有定义,但未定义将使用哪一个。尝试此操作时会在控制台中看到错误:
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 方代码中的三个字母前缀的原因。一些第 3 方开发人员仍然使用两个字母,但那是另一回事了。
Swift 有更多的命名空间——它们基于模块。当使用纯 @objc
属性时,包含模块名称是一个安全的选择。为了避免可能的歧义。
勾选 NSEntityDescription
class for example - managedObjectClassName
属性:
The name of the class that represents the receiver’s entity.
有很多东西可以利用 Objective-C 运行时特性,很多东西仅基于名称(字符串),...
在 Apple 生成的代码中(例如,Core Data NSManagedObject
subclasses)我看到了这个:
@objc(LPFile)
public class LPFile: NSManagedObject {
...
}
我的问题是: 为什么 @objc
声明如上,而不是:
@objc public class LPFile: NSManagedObject {
...
}
或
@objcMembers public class LPFile: NSManagedObject {
...
}
单独的 @objc(identifier)
声明有什么特别之处?我似乎无法找到关于它的文档,谷歌搜索只会出现其他两种方法。谢谢。
(注意:我知道 class 前缀不是惯用的 Swift。)
@Alladinian 是对的。假设你有一个框架 SharedSwift
有两个 classes:
@objc public class Foo: NSObject {}
@objc(Bar) public class Bar: NSObject {}
你可以在Objective-C代码中引入这个框架,直接使用这两个class:
@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]);
... returns SharedSwift.Foo
在一种情况下 (@objc
) 和 Bar
在另一种情况下 (@objc(Bar)
).
SharedSwift.Foo Bar
让我们将 AnotherSwift
框架添加到具有相同 classes 的组合中,并尝试使用来自两者的 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 在两个框架中都有定义,但未定义将使用哪一个。尝试此操作时会在控制台中看到错误:
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 方代码中的三个字母前缀的原因。一些第 3 方开发人员仍然使用两个字母,但那是另一回事了。
Swift 有更多的命名空间——它们基于模块。当使用纯 @objc
属性时,包含模块名称是一个安全的选择。为了避免可能的歧义。
勾选 NSEntityDescription
class for example - managedObjectClassName
属性:
The name of the class that represents the receiver’s entity.
有很多东西可以利用 Objective-C 运行时特性,很多东西仅基于名称(字符串),...