NSDictionary <FBGraphUser> *用户语法说明

在Facebook iOS SDK请求返回以下处理程序:

^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) { } 

用户variables,然后可以像这些调用访问…

  self.userNameLabel.text = user.name; self.userProfileImage.profileID = user.id; 

这个语法有点类似于语法id <protocolDelegate> object语法,它是一个通用的属性声明,除了NSDictionary明确地是id对象,并且该字典符合协议? 但是,点语法是从哪里来的,以及如何声明一个任意的NSFoundation对象对应于一个协议,而不需要将对象本身进行子类化并使之符合?

我做了点符号和NSDictionary的一些额外的研究,似乎是不可能在字典上使用点符号而不添加一个类别NSDictionary。 但是,我没有在Apple文档中看到任何有关<>语法的参考,表明这个特定的NSDictionary实例符合这个符号。

Facebook的文档在这个包装的工作方式上有点稀疏:

FBGraphUser协议代表了Facebook用户对象最常用的属性。 它可以用来访问已经用FBGraphObject外观包装的NSDictionary对象。

如果遵循这个导致FBGraphObject文档,那么有方法返回符合这个“门面…”的字典,但没有进一步解释如何包装字典。

所以我想我的问题是几个:

  1. 下面的代码看起来像什么使这种语法工作?
  2. 它为什么存在?
  3. 为什么Facebook会以这种方式实现它,而不是仅仅把一个对象转换成数据呢?

任何解释或见解将非常感激!

基本上, NSDictionary<FBGraphUser> *user ,意味着一个从NSDictionaryinheritance的对象,添加由FBGraphUser协议声明的function(特别是types访问)。

FBGraphObject文档 ( FBGraphUser协议扩展了FBGraphObject协议)详细介绍了这种方法背后的原因。 什么可能会让你感到困惑的是, FBGraphObject是一个协议( 这里描述)和一个类( 在这里描述),从NSMutableDictionaryinheritance。

就内部实现而言,这是一些相当先进的Objective-Cdynamic魔术,你可能不需要担心。 所有你需要知道的是,如果你愿意的话,你可以把对象看作字典,或者使用协议中的附加方法。 如果你真的想知道细节,你可以看看FBGraphObject的源代码 ,特别是这些方法:

 #pragma mark - #pragma mark NSObject overrides // make the respondsToSelector method do the right thing for the selectors we handle - (BOOL)respondsToSelector:(SEL)sel { return [super respondsToSelector:sel] || ([FBGraphObject inferredImplTypeForSelector:sel] != SelectorInferredImplTypeNone); } - (BOOL)conformsToProtocol:(Protocol *)protocol { return [super conformsToProtocol:protocol] || ([FBGraphObject isProtocolImplementationInferable:protocol checkFBGraphObjectAdoption:YES]); } // returns the signature for the method that we will actually invoke - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { SEL alternateSelector = sel; // if we should forward, to where? switch ([FBGraphObject inferredImplTypeForSelector:sel]) { case SelectorInferredImplTypeGet: alternateSelector = @selector(objectForKey:); break; case SelectorInferredImplTypeSet: alternateSelector = @selector(setObject:forKey:); break; case SelectorInferredImplTypeNone: default: break; } return [super methodSignatureForSelector:alternateSelector]; } // forwards otherwise missing selectors that match the FBGraphObject convention - (void)forwardInvocation:(NSInvocation *)invocation { // if we should forward, to where? switch ([FBGraphObject inferredImplTypeForSelector:[invocation selector]]) { case SelectorInferredImplTypeGet: { // property getter impl uses the selector name as an argument... NSString *propertyName = NSStringFromSelector([invocation selector]); [invocation setArgument:&propertyName atIndex:2]; //... to the replacement method objectForKey: invocation.selector = @selector(objectForKey:); [invocation invokeWithTarget:self]; break; } case SelectorInferredImplTypeSet: { // property setter impl uses the selector name as an argument... NSMutableString *propertyName = [NSMutableString stringWithString:NSStringFromSelector([invocation selector])]; // remove 'set' and trailing ':', and lowercase the new first character [propertyName deleteCharactersInRange:NSMakeRange(0, 3)]; // "set" [propertyName deleteCharactersInRange:NSMakeRange(propertyName.length - 1, 1)]; // ":" NSString *firstChar = [[propertyName substringWithRange:NSMakeRange(0,1)] lowercaseString]; [propertyName replaceCharactersInRange:NSMakeRange(0, 1) withString:firstChar]; // the object argument is already in the right place (2), but we need to set the key argument [invocation setArgument:&propertyName atIndex:3]; // and replace the missing method with setObject:forKey: invocation.selector = @selector(setObject:forKey:); [invocation invokeWithTarget:self]; break; } case SelectorInferredImplTypeNone: default: [super forwardInvocation:invocation]; return; } } 

这个语法有点类似于语法id对象语法

“有点相似”? 如何“相同”?

并且该字典符合该协议

那么,声明说你必须传入一个类NSDictionary的对象,同时符合FBGraphUser协议。

但是,点语法来自哪里呢?

我不明白这一点。 它来自编写有关代码的程序员。 这是可能的,因为FBGraphUser协议声明了一些属性,然后可以通过点符号访问。

以及如何声明一个任意的NSFoundation对象对应于一个协议,而无需将对象本身进行子类化并使之符合?

这不是所谓的“NSFoundation”,只是基金会。 这不是不符合协议的“对应”(因为它“符合”)的对象,而是它的类。 你只是展示了自己的语法。

它是如何实现的? 简单:一个类别。

 #import <Foundation/Foundation.h> @protocol Foo @property (readonly, assign) int answer; @end @interface NSDictionary (MyCategory) <Foo> @end @implementation NSDictionary (MyCategory) - (int)answer { return 42; } @end int main() { NSDictionary *d = [NSDictionary dictionary]; NSLog(@"%d", d.answer); return 0; } 

这是一个SSCCE,也就是说,它编译和运行,尝试它!

下面的代码看起来像什么使这种语法工作?

回答上面。

它为什么存在?

因为语言是这样定义的。

为什么Facebook会以这种方式实现它,而不是仅仅把一个对象转换成数据呢?

我不知道,问Facebook的人。