alt*_*yus 13 iphone objective-c dynamic-typing ios
看一下NSArray.h中的NSArray创建方法块.
返回id的方法是否有正当理由不返回instancetype?
Apple甚至努力添加内联注释,让我们知道id在这种情况下会返回一个NSArray.
@interface NSArray (NSArrayCreation)
+ (instancetype)array;
+ (instancetype)arrayWithObject:(id)anObject;
+ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
+ (instancetype)arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (instancetype)arrayWithArray:(NSArray *)array;
- (instancetype)init; /* designated initializer */
- (instancetype)initWithObjects:(const id [])objects count:(NSUInteger)cnt; /* designated initializer */
- (instancetype)initWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
- (instancetype)initWithArray:(NSArray *)array;
- (instancetype)initWithArray:(NSArray *)array copyItems:(BOOL)flag;
+ (id /* NSArray * */)arrayWithContentsOfFile:(NSString *)path;
+ (id /* NSArray * */)arrayWithContentsOfURL:(NSURL *)url;
- (id /* NSArray * */)initWithContentsOfFile:(NSString *)path;
- (id /* NSArray * */)initWithContentsOfURL:(NSURL *)url;
@end
Run Code Online (Sandbox Code Playgroud)
我能提出这些特殊方法的唯一方法就是Apple的这个指导
"由aURL标识的位置的数组表示必须只包含属性列表>对象(NSString,NSData,NSArray或NSDictionary对象).这个>数组包含的对象是不可变的,即使数组是可变的."
但是,这对我来说还没有解释id over instancetype的用法,因为它们仍然允许NSArray子类返回自己的 instancetype
NSDictionary遵循完全相同的模式,其中创建包含文件或URL内容的字典,并使用id所有其他创建方法instancetype
- (instancetype)initWithObjectsAndKeys:(id)firstObject, ... NS_REQUIRES_NIL_TERMINATION;
- (instancetype)initWithDictionary:(NSDictionary *)otherDictionary;
- (instancetype)initWithDictionary:(NSDictionary *)otherDictionary copyItems:(BOOL)flag;
- (instancetype)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys;
+ (id /* NSDictionary * */)dictionaryWithContentsOfFile:(NSString *)path;
+ (id /* NSDictionary * */)dictionaryWithContentsOfURL:(NSURL *)url;
- (id /* NSDictionary * */)initWithContentsOfFile:(NSString *)path;
- (id /* NSDictionary * */)initWithContentsOfURL:(NSURL *)url;
Run Code Online (Sandbox Code Playgroud)
我知道Apple只是在替换id基础类,instancetype但在单个类中使用它的模式不一致是我们自己使用的指导,还是他们只是没有完成他们开始工作的课程?
稍微扩展我想探索dictionaryWithContentsOfFile在NSMutableDictionary上调用的返回类型
NSString * plistPath = [[NSBundle mainBundle] pathForResource:@"myFile" ofType:@"plist"];
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
if ([ myDictionary isKindOfClass:[NSMutableDictionary class]])
{
NSLog(@"This is a mutable dictionary why id and not instancetype?");
[myDictionary setObject:@"I can mutate the dictionary" forKey:@"newKey"];
}
NSLog (@"%@", myDictionary[@"newKey"]);
return YES;
}
Run Code Online (Sandbox Code Playgroud)
以下内容输出到我的控制台:
这是一个可变字典为什么id而不是instancetype?
我可以改变字典
因此,我能够将新的键和对象添加到字典中.
好的,所以要回答这个问题,首先我们需要知道什么是类集群设计模式?
来自Apple的文档:
类集群是Foundation框架广泛使用的设计模式.类集群在公共抽象超类下组合了许多私有具体子类.以这种方式对类进行分组简化了面向对象框架的公开可见体系结构,而不会降低其功能丰富性.类集群基于抽象工厂设计模式.
所以超类将决定我们将为新创建的对象提供什么类型
现在因为这些方法在NSArray和之间共享NSMutableArray,结果可能不同,然后返回id,因为我们不知道将返回什么对象.(mutableArray或immutableArray).
+ (id /* NSArray * */)arrayWithContentsOfFile:(NSString *)path;
+ (id /* NSArray * */)arrayWithContentsOfURL:(NSURL *)url;
- (id /* NSArray * */)initWithContentsOfFile:(NSString *)path;
- (id /* NSArray * */)initWithContentsOfURL:(NSURL *)url;
Run Code Online (Sandbox Code Playgroud)
仅NSArray当消息发送到NSArray并且NSMutableArray方法已发送到时,这些方法才会返回NSMutableArray.这就是为什么他们回来了instancetype
+ (instancetype)arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (instancetype)arrayWithArray:(NSArray *)array;
- (instancetype)init;
Run Code Online (Sandbox Code Playgroud)
好的,所以我们说上面的方法只返回接收器的实例类型.但是,如果我们想要arrayWithArray方法总是返回,immutableArray无论谁是接收者?
这意味着NSMutableArray将获得与instanceType不同的类型,因为NSArray不是NSMutableArray类型,在这种情况下我们会将方法更改为:
// from
+ (instancetype)arrayWithArray:(NSArray *)array;
// to
+ (id)arrayWithArray:(NSArray *)array;
Run Code Online (Sandbox Code Playgroud)
我们说现在返回id,尽管对象的类型.
更新:
类似于您的代码的示例
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"myFile" ofType:@"plist"];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
NSMutableDictionary *dict2 = [[NSMutableDictionary alloc] init];
NSLog(@"%@", NSStringFromClass([dict class])); // prints __NSCFDictionary // converted to immutable
NSLog(@"%@", NSStringFromClass([dict2 class])); // prints __NSDictionaryM, its mutable
[dict setObject:@"obj" forKey:@"key"]; // this will do nothing, because its immutable, we can't add new object
Run Code Online (Sandbox Code Playgroud)
以下是Apple对使用的说法isKindOfClass:检查类集群的可变性
在类集群表示的对象上使用此方法时要小心.由于类集群的性质,您获得的对象可能并不总是您期望的类型.如果调用返回类集群的方法,则该方法返回的确切类型是您可以对该对象执行的操作的最佳指示.例如,如果方法返回指向NSArray对象的指针,则不应使用此方法来查看该数组是否可变,如以下代码所示:
// DO NOT DO THIS!
if ([myArray isKindOfClass:[NSMutableArray class]])
{
// Modify the object
}
Run Code Online (Sandbox Code Playgroud)
链接:https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/isKindOfClass:
类簇可能会返回一个类,而不是您创建它们的类。对于基础类来说通常是这样,因为它们在许多情况下会创建某种优化的类。该类仍将从 isKindOfClass 返回 YES:
此外,一些免费桥接类返回在 Foundation 和 Core Foundation 之间共享的类。NSCFString 就是一个例子。
| 归档时间: |
|
| 查看次数: |
1273 次 |
| 最近记录: |