FBGraphObject.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * Copyright 2010-present Facebook.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <Foundation/Foundation.h>
  17. @protocol FBOpenGraphObject;
  18. @protocol FBOpenGraphAction;
  19. /*!
  20. @protocol
  21. @abstract
  22. The `FBGraphObject` protocol is the base protocol which enables typed access to graph objects and
  23. open graph objects. Inherit from this protocol or a sub-protocol in order to introduce custom types
  24. for typed access to Facebook objects.
  25. @discussion
  26. The `FBGraphObject` protocol is the core type used by the Facebook SDK for iOS to
  27. represent objects in the Facebook Social Graph and the Facebook Open Graph (OG).
  28. The `FBGraphObject` class implements useful default functionality, but is rarely
  29. used directly by applications. The `FBGraphObject` protocol, in contrast is the
  30. base protocol for all graph object access via the SDK.
  31. Goals of the FBGraphObject types:
  32. <ul>
  33. <li> Lightweight/maintainable/robust </li>
  34. <li> Extensible and resilient to change, both by Facebook and third party (OG) </li>
  35. <li> Simple and natural extension to Objective-C </li>
  36. </ul>
  37. The FBGraphObject at its core is a duck typed (if it walks/swims/quacks...
  38. its a duck) model which supports an optional static facade. Duck-typing achieves
  39. the flexibility necessary for Social Graph and OG uses, and the static facade
  40. increases discoverability, maintainability, robustness and simplicity.
  41. The following excerpt from the PlacePickerSample shows a simple use of the
  42. a facade protocol `FBGraphPlace` by an application:
  43. <pre>
  44. &dash; (void)placePickerViewControllerSelectionDidChange:(FBPlacePickerViewController *)placePicker
  45. {
  46. id&#060;FBGraphPlace&#062; place = placePicker.selection;
  47. // we'll use logging to show the simple typed property access to place and location info
  48. NSLog(@"place=%@, city=%@, state=%@, lat long=%@ %@",
  49. place.name,
  50. place.location.city,
  51. place.location.state,
  52. place.location.latitude,
  53. place.location.longitude);
  54. }
  55. </pre>
  56. Note that in this example, access to common place information is available through typed property
  57. syntax. But if at some point places in the Social Graph supported additional fields "foo" and "bar", not
  58. reflected in the `FBGraphPlace` protocol, the application could still access the values like so:
  59. <pre>
  60. NSString *foo = [place objectForKey:@"foo"]; // perhaps located at the ... in the preceding example
  61. NSNumber *bar = [place objectForKey:@"bar"]; // extensibility applies to Social and Open graph uses
  62. </pre>
  63. In addition to untyped access, applications and future revisions of the SDK may add facade protocols by
  64. declaring a protocol inheriting the `FBGraphObject` protocol, like so:
  65. <pre>
  66. &#064;protocol MyGraphThing&#060;FBGraphObject&#062;
  67. &#064;property (copy, nonatomic) NSString *objectID;
  68. &#064;property (copy, nonatomic) NSString *name;
  69. &#064;end
  70. </pre>
  71. Important: facade implementations are inferred by graph objects returned by the methods of the SDK. This
  72. means that no explicit implementation is required by application or SDK code. Any `FBGraphObject` instance
  73. may be cast to any `FBGraphObject` facade protocol, and accessed via properties. If a field is not present
  74. for a given facade property, the property will return nil.
  75. The following layer diagram depicts some of the concepts discussed thus far:
  76. <pre>
  77. *-------------* *------------* *-------------**--------------------------*
  78. Facade --> | FBGraphUser | |FBGraphPlace| | MyGraphThing|| MyGraphPersonExtentension| ...
  79. *-------------* *------------* *-------------**--------------------------*
  80. *------------------------------------* *--------------------------------------*
  81. Transparent impl --> | FBGraphObject (instances) | | CustomClass&#060;FBGraphObject&#062; |
  82. *------------------------------------* *--------------------------------------*
  83. *-------------------**------------------------* *-----------------------------*
  84. Apparent impl --> |NSMutableDictionary||FBGraphObject (protocol)| |FBGraphObject (class methods)|
  85. *-------------------**------------------------* *-----------------------------*
  86. </pre>
  87. The *Facade* layer is meant for typed access to graph objects. The *Transparent impl* layer (more
  88. specifically, the instance capabilities of `FBGraphObject`) are used by the SDK and app logic
  89. internally, but are not part of the public interface between application and SDK. The *Apparent impl*
  90. layer represents the lower-level "duck-typed" use of graph objects.
  91. Implementation note: the SDK returns `NSMutableDictionary` derived instances with types declared like
  92. one of the following:
  93. <pre>
  94. NSMutableDictionary&#060;FBGraphObject&#062; *obj; // no facade specified (still castable by app)
  95. NSMutableDictionary&#060;FBGraphPlace&#062; *person; // facade specified when possible
  96. </pre>
  97. However, when passing a graph object to the SDK, `NSMutableDictionary` is not assumed; only the
  98. FBGraphObject protocol is assumed, like so:
  99. <pre>
  100. id&#060;FBGraphObject&#062; anyGraphObj;
  101. </pre>
  102. As such, the methods declared on the `FBGraphObject` protocol represent the methods used by the SDK to
  103. consume graph objects. While the `FBGraphObject` class implements the full `NSMutableDictionary` and KVC
  104. interfaces, these are not consumed directly by the SDK, and are optional for custom implementations.
  105. */
  106. @protocol FBGraphObject<NSObject>
  107. /*!
  108. @method
  109. @abstract
  110. Returns the number of properties on this `FBGraphObject`.
  111. */
  112. - (NSUInteger)count;
  113. /*!
  114. @method
  115. @abstract
  116. Returns a property on this `FBGraphObject`.
  117. @param aKey name of the property to return
  118. */
  119. - (id)objectForKey:(id)aKey;
  120. /*!
  121. @method
  122. @abstract
  123. Returns an enumerator of the property names on this `FBGraphObject`.
  124. */
  125. - (NSEnumerator *)keyEnumerator;
  126. /*!
  127. @method
  128. @abstract
  129. Removes a property on this `FBGraphObject`.
  130. @param aKey name of the property to remove
  131. */
  132. - (void)removeObjectForKey:(id)aKey;
  133. /*!
  134. @method
  135. @abstract
  136. Sets the value of a property on this `FBGraphObject`.
  137. @param anObject the new value of the property
  138. @param aKey name of the property to set
  139. */
  140. - (void)setObject:(id)anObject forKey:(id)aKey;
  141. @optional
  142. /*!
  143. @abstract
  144. This property signifies that the current graph object is provisioned for POST (as a definition
  145. for a new or updated graph object), and should be posted AS-IS in its JSON encoded form, whereas
  146. some graph objects (usually those embedded in other graph objects as references to existing objects)
  147. may only have their "id" or "url" posted.
  148. */
  149. @property (nonatomic, assign) BOOL provisionedForPost;
  150. @end
  151. /*!
  152. @class
  153. @abstract
  154. Static class with helpers for use with graph objects
  155. @discussion
  156. The public interface of this class is useful for creating objects that have the same graph characteristics
  157. of those returned by methods of the SDK. This class also represents the internal implementation of the
  158. `FBGraphObject` protocol, used by the Facebook SDK. Application code should not use the `FBGraphObject` class to
  159. access instances and instance members, favoring the protocol.
  160. */
  161. @interface FBGraphObject : NSMutableDictionary<FBGraphObject>
  162. /*!
  163. @method
  164. @abstract
  165. Used to create a graph object, usually for use in posting a new graph object or action.
  166. */
  167. + (NSMutableDictionary<FBGraphObject> *)graphObject;
  168. /*!
  169. @method
  170. @abstract
  171. Used to wrap an existing dictionary with a `FBGraphObject` facade
  172. @discussion
  173. Normally you will not need to call this method, as the Facebook SDK already "FBGraphObject-ifys" json objects
  174. fetch via `FBRequest` and `FBRequestConnection`. However, you may have other reasons to create json objects in your
  175. application, which you would like to treat as a graph object. The pattern for doing this is that you pass the root
  176. node of the json to this method, to retrieve a wrapper. From this point, if you traverse the graph, any other objects
  177. deeper in the hierarchy will be wrapped as `FBGraphObject`'s in a lazy fashion.
  178. This method is designed to avoid unnecessary memory allocations, and object copying. Due to this, the method does
  179. not copy the source object if it can be avoided, but rather wraps and uses it as is. The returned object derives
  180. callers shoudl use the returned object after calls to this method, rather than continue to call methods on the original
  181. object.
  182. @param jsonDictionary the dictionary representing the underlying object to wrap
  183. */
  184. + (NSMutableDictionary<FBGraphObject> *)graphObjectWrappingDictionary:(NSDictionary *)jsonDictionary;
  185. /*!
  186. @method
  187. @abstract
  188. Used to create a graph object that's provisioned for POST, usually for use in posting a new Open Graph Action.
  189. */
  190. + (NSMutableDictionary<FBOpenGraphAction> *)openGraphActionForPost;
  191. /*!
  192. @method
  193. @abstract
  194. Used to create a graph object that's provisioned for POST, usually for use in posting a new Open Graph object.
  195. */
  196. + (NSMutableDictionary<FBOpenGraphObject> *)openGraphObjectForPost;
  197. /*!
  198. @method
  199. @abstract
  200. Used to create a graph object that's provisioned for POST, usually for use in posting a new Open Graph object.
  201. @param type the object type name, in the form namespace:typename
  202. @param title a title for the object
  203. @param image the image property for the object
  204. @param url the url property for the object
  205. @param description the description for the object
  206. */
  207. + (NSMutableDictionary<FBOpenGraphObject> *)openGraphObjectForPostWithType:(NSString *)type
  208. title:(NSString *)title
  209. image:(id)image
  210. url:(id)url
  211. description:(NSString *)description;
  212. /*!
  213. @method
  214. @abstract
  215. Used to compare two `FBGraphObject`s to determine if represent the same object. We do not overload
  216. the concept of equality as there are various types of equality that may be important for an `FBGraphObject`
  217. (for instance, two different `FBGraphObject`s could represent the same object, but contain different
  218. subsets of fields).
  219. @param anObject an `FBGraphObject` to test
  220. @param anotherObject the `FBGraphObject` to compare it against
  221. */
  222. + (BOOL)isGraphObjectID:(id<FBGraphObject>)anObject sameAs:(id<FBGraphObject>)anotherObject;
  223. @end