当前位置:K88软件开发文章中心编程语言Objective-CObjective-C01 → 文章内容

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-10 11:12:17

法返回的类型是否合法)。
Clang的这个好处来自于 related result type,
意味着:messages sent to one of alloc and init methods will have the same static type as the instance of the receiver class (发送到 alloc 或者 init 方法的消息会有同样的静态类型检查是否为接受类的实例。
)更多的关于这个自动定义相关返回类型的约定请查看 Clang Language Extensions guide 的appropriate section 一个相关的返回类型可以明确地规定用 instancetype 关键字作为返回类型,
并且它可以在一些工厂方法或者构造器方法的场景下很有用。
它可以提示编译器正确地检查类型,
并且更加重要的是,
这同时适用于它的子类。
@interface ZOCPerson+ (instancetype)personWithName:(NSString *)name;
@end虽然如此,
根据 clang 的定义,
id 可以被编译器提升到 instancetype 。
在 alloc 或者 init 中,
我们强烈建议对所有返回类的实例的类方法和实例方法使用 instancetype 类型。
在你的 API 中要构成习惯以及保持始终如一的,
此外,
通过对你代码的小调整你可以提高可读性:在简单的浏览的时候你可以区分哪些方法是返回你类的实例的。
你以后会感谢这些注意过的小细节的。
参考http://tewha.net/2013/02/why-you-should-use-instancetype-instead-of-id/http://tewha.net/2013/01/when-is-id-promoted-to-instancetype/http://clang.llvm.org/docs/LanguageExtensions.html#related-result-typeshttp://nshipster.com/instancetype/初始化模式类簇 (class cluster)类簇在Apple的文档中这样描述:an architecture that groups a number of private, concrete subclasses under a public, abstract superclass. (一个在共有的抽象超类下设置一组私有子类的架构)如果这个描述听起来很熟悉,
说明你的直觉是对的。
Class cluster 是 Apple 对抽象工厂设计模式的称呼。
class cluster 的想法很简单,
你经常有一个抽象类在初始化期间处理信息,
经常作为一个构造器里面的参数或者环境中读取,
来完成特定的逻辑并且实例化子类。
这个"
public facing"
应该知晓它的子类而且返回适合的私有子类。
这个模式非常有用,
因为它减少了构造器调用中的复杂性,
只需要知道接口如何与对象通信,
而不需要知道怎么实现。
Class clusters 在 Apple 的Framework 中广泛使用:一些明显的例子比如 NSNumber 可以返回不同哦给你的子类,
取决于 数字类型如何提供 (Integer, Float, etc...) 或者 NSArray 返回不同的最优存储策略的子类。
这个模式的精妙的地方在于,
调用者可以完全不管子类,
事实上,
这可以用在设计一个库,
可以用来交换实际的返回的类,
而不用去管相关的细节,
因为它们都遵从抽象超类的方法。
我们的经验是使用类簇可以帮助移除很多条件语句。
一个经典的例子是如果你有为 iPad 和 iPhone 写的一样的 UIViewController 子类,
但是在不同的设备上有不同的行为。
比较基础的实现是用条件语句检查设备,
然后执行不同的逻辑。
虽然刚开始可能不错,
但是随着代码的增长,
运行逻辑也会趋于复杂。
一个更好的实现的设计是创建一个抽象而且宽泛的 view controller 来包含所有的共享逻辑,
并且对于不同设备有两个特别的子例。
通用的 view controller 会检查当前设备并且返回适当的子类。
@implementation ZOCKintsugiPhotoViewController- (id)initWithPhotos:(NSArray *)photos{ if ([self isMemberOfClass:ZOCKintsugiPhotoViewController.class]) { self = nil;
if ([UIDevice isPad]) { self = [[ZOCKintsugiPhotoViewController_iPad alloc] initWithPhotos:photos];
{
else { self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos];
{
return self;
{
return [super initWithNibName:nil bundle:nil];
{
@end之前的代码的例子展示了如何创建一个类簇。
首先,
[self isMemberOfClass:ZOCKintsugiPhotoViewController.class] 来避免在子类中重载初始化方法,
来避免无限的递归。
当 [[ZOCKintsugiPhotoViewController alloc] initWithPhotos:photos] 得到调用的时候之前的检查会变成 true 的,
self = nil 是用来移除所有到 ZOCKintsugiPhotoViewController 实例的引用的,
它会被释放,
按照这个逻辑来检查哪个类应该被初始化。
让我们假设在 iPhone 上运行了这个代码,
ZOCKintsugiPhotoViewController_iPhone 没有重载initWithPhotos:,
在这个情况下,
当执行 self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos];
的时候,
ZOCKintsugiPhotoViewController 会被调用,
并且当第一次检查的时候,
这样不会让 ZOCKintsugiPhotoViewController 检查会变成 false 调用return [super initWithNibName:nil bundle:nil];

这会让 继续初始化执行正确的初始化之前的会话。
单例如果可能,
请尽量避免使用单例而是依赖注入。
然而,
如果一定要用,
请使用一个线程安全的模式来创建共享的实例。
对于GCD,
用 dispatch_once() 函数就可以咯。
+ (instancetype)sharedInstance{ static id sharedInstance = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&
onceToken, ^{ sharedInstance = [[self alloc] init];
{
);
return sharedInstance;
{
使用dispatch_once(),
来控制代码同步,
取代了原来老的约定俗成的用法。
+ (instancetype)sharedInstance{ static id sharedInstance;
@synchronized(self) { if (sharedInstance == nil) { sharedInstance = [[MyClass alloc] init];
{
{
return sharedInstance;
{
dispatch_once() 的优点是,
它更快,
而且语法上更干净,
因为dispatch_once()的意思就是 ”把一些东西执行一次“,
就像我们做的一样。
这样同时可以避免possible and sometimes prolific crashes.经典的可以接受的单例对象的例子是一个设备的 GPS 以及 动作传感器。
即使单例对象可以被子类化,
这个情况可以十分有用。
这个接口应该证明给出的类是趋向于使用单例的。
然而,
经常使用一个单独的公开的 sharedInstance 类方法就够了,
并且不可写的

上一页  [1] [2] [3] [4] [5]  下一页