ios - NSDictionary<FBGraphUser> *user syntax explanation -
in facebook ios sdk requests returned following handler:
^(fbrequestconnection *connection, nsdictionary<fbgraphuser> *user, nserror *error) { }
the user variable can accessed calls these...
self.usernamelabel.text = user.name; self.userprofileimage.profileid = user.id;
this syntax similar syntax id <protocoldelegate> object
syntax common property declaration, except nsdictionary id object explicitely, , dictionary conforms protocol? dot syntax come , how 1 state arbitrary nsfoundation object corresponds protocol without subclassing object , making conform?
i did additional research dot notation , nsdictionary , appears not possible use dot notation on dictionary without adding category nsdictionary. however, did not see reference of <> syntax in apple documentation indicate particular instance of nsdictionary conformed notation.
and facebook documentation little sparse on how wrapping works:
the fbgraphuser protocol represents commonly used properties of facebook user object. may used access nsdictionary object has been wrapped fbgraphobject facade.
if 1 follows lead fbgraphobject documentation there methods return dictionaries conform "facade..." no further explanation on how 1 goes wrapping dictionary.
so guess questions few:
- what underlying code make sort of syntax work?
- why exist?
- why facebook implement way opposed making object can convert data into?
any explanation or insight appreciated!
basically, nsdictionary<fbgraphuser> *user
, implies object inherits nsdictionary
, adding functionality (specifically, typed access) declared fbgraphuser
protocol.
the reasons behind approach described in quite bit of detail in fbgraphobject documentation (the fbgraphuser
protocol extends fbgraphobject
protocol). might confusing fbgraphobject
protocol (described here) , class (described here), inherits nsmutabledictionary
.
in terms of inner implementation, it's pretty advanced objective-c dynamic magic, don't want worry about. need know can treat object dictionary if wish, or use additional methods in protocol. if want know details, can @ source code fbgraphobject, in particular, these methods:
#pragma mark - #pragma mark nsobject overrides // make respondstoselector method right thing selectors 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 signature method invoke - (nsmethodsignature *)methodsignatureforselector:(sel)sel { sel alternateselector = sel; // if should forward, 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 match fbgraphobject convention - (void)forwardinvocation:(nsinvocation *)invocation { // if should forward, where? switch ([fbgraphobject inferredimpltypeforselector:[invocation selector]]) { case selectorinferredimpltypeget: { // property getter impl uses selector name argument... nsstring *propertyname = nsstringfromselector([invocation selector]); [invocation setargument:&propertyname atindex:2]; //... replacement method objectforkey: invocation.selector = @selector(objectforkey:); [invocation invokewithtarget:self]; break; } case selectorinferredimpltypeset: { // property setter impl uses selector name argument... nsmutablestring *propertyname = [nsmutablestring stringwithstring:nsstringfromselector([invocation selector])]; // remove 'set' , trailing ':', , lowercase 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]; // object argument in right place (2), need set key argument [invocation setargument:&propertyname atindex:3]; // , replace missing method setobject:forkey: invocation.selector = @selector(setobject:forkey:); [invocation invokewithtarget:self]; break; } case selectorinferredimpltypenone: default: [super forwardinvocation:invocation]; return; } }
Comments
Post a Comment