[英]NSDictionary<FBGraphUser> *user syntax explanation
在Facebook iOS SDK中,使用以下處理程序返回請求:
^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) { }
然后可以使用這些調用來訪問用戶變量......
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文檔,那么有一些方法返回符合這個“外觀......”的字典,但沒有關於如何包裝字典的進一步解釋。
所以我想我的問題有幾點:
任何解釋或見解將非常感謝!
基本上, NSDictionary<FBGraphUser> *user
表示一個繼承自NSDictionary
的對象,添加了FBGraphUser
協議聲明的功能(特別是類型化訪問)。
這種方法背后的原因在FBGraphObject文檔中有相當詳細的描述 ( FBGraphUser
協議擴展了FBGraphObject
協議)。 你可能會感到困惑的是FBGraphObject
是一個協議( 在這里描述)和一個類( 在這里描述),它繼承自NSMutableDictionary
。
在內部實現方面,它是一些非常先進的Objective-C動態魔法,你可能不想擔心。 您需要知道的是,如果您願意,可以將對象視為字典,或者使用協議中的其他方法。 如果您真的想知道詳細信息,可以查看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對象語法
“有點類似”? 怎么“相同”?
那個字典符合協議
Nah,聲明說你必須傳入一個類是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的人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.