What exactly +[NSURLProtocol setProperty:forKey:inRequest:] does - objective-c

NSURLProtocol defines following methods:
/*!
#method propertyForKey:inRequest:
#abstract Returns the property in the given request previously
stored with the given key.
#discussion The purpose of this method is to provide an interface
for protocol implementors to access protocol-specific information
associated with NSURLRequest objects.
#param key The string to use for the property lookup.
#param request The request to use for the property lookup.
#result The property stored with the given key, or nil if no property
had previously been stored with the given key in the given request.
*/
+ (nullable id)propertyForKey:(NSString *)key inRequest:(NSURLRequest *)request;
/*!
#method setProperty:forKey:inRequest:
#abstract Stores the given property in the given request using the
given key.
#discussion The purpose of this method is to provide an interface
for protocol implementors to customize protocol-specific
information associated with NSMutableURLRequest objects.
#param value The property to store.
#param key The string to use for the property storage.
#param request The request in which to store the property.
*/
+ (void)setProperty:(id)value forKey:(NSString *)key inRequest:(NSMutableURLRequest *)request;
/*!
#method removePropertyForKey:inRequest:
#abstract Remove any property stored under the given key
#discussion Like setProperty:forKey:inRequest: above, the purpose of this
method is to give protocol implementors the ability to store
protocol-specific information in an NSURLRequest
#param key The key whose value should be removed
#param request The request to be modified
*/
+ (void)removePropertyForKey:(NSString *)key inRequest:(NSMutableURLRequest *)request;
But, if I trying to associate NSURLAuthenticationChallenge with request, using following code
[NSURLProtocol setProperty:challenge forKey:#"challenge" inRequest:self.request];
I see next error in log:
2016-03-20 18:00:41.252 Web#Work[6084:586155] ERROR: createEncodedCachedResponseAndRequestForXPCTransmission - Invalid protocol-property list - CFURLRequestRef. protoProps=<CFBasicHash 0x7f98ec6dcca0 [0x10684e180]>{type = mutable dict, count = 3,
entries =>
0 : <CFString 0x101f47938 [0x10684e180]>{contents = "challenge"} = <NSURLAuthenticationChallenge: 0x7f98ec4cd700>
1 : <CFString 0x7f98e9fd03a0 [0x10684e180]>{contents = "Accept-Encoding"} = <CFBasicHash 0x7f98ec7c4490 [0x10684e180]>{type = mutable dict, count = 1,
entries =>
2 : <CFString 0x7f98ec78b930 [0x10684e180]>{contents = "Accept-Encoding"} = <CFString 0x106330828 [0x10684e180]>{contents = "gzip, deflate"}
}
2 : <CFString 0x1063310e8 [0x10684e180]>{contents = "kCFURLRequestAllowAllPOSTCaching"} = <CFBoolean 0x10684ebf0 [0x10684e180]>{value = true}
}
From this message, I suspect that only property list supported objects may be associated with NSURLRequest using this API. But I do not completely understand why.
Also, my question is for which purpose this API should be used. How to use it correctly? I want to know what exactly setProperty:forKey:inRequest: does, because it seems to do more work, than simply associate objects with request.
UPD So, minimal verifiable example. Very simple NSURLProtocol subclass:
#import "MyURLProtocol.h"
#define kOurRecursiveRequestFlagProperty #"recursive"
#interface MyURLProtocol ()
#property NSURLConnection *connection;
#end
#implementation MyURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
return ![[[self class] propertyForKey:kOurRecursiveRequestFlagProperty inRequest:request] boolValue];
}
- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id <NSURLProtocolClient>)client {
return [super initWithRequest:request cachedResponse:cachedResponse client:client];
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
- (void)startLoading {
NSMutableURLRequest* mutableRequest = [[self request] mutableCopy];
[[self class] setProperty:#YES forKey:kOurRecursiveRequestFlagProperty inRequest:mutableRequest];
// Associate any non-property list object with mutableRequest to reproduce issue.
[[self class] setProperty:[UIApplication sharedApplication] forKey:#"dummyKey" inRequest:mutableRequest];
self.connection = [[NSURLConnection alloc] initWithRequest:mutableRequest delegate:self startImmediately:YES];
}
- (void)stopLoading {
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[[self client] URLProtocolDidFinishLoading:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[[self client] URLProtocol:self didLoadData:data];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse {
return request;
}
#end
UPD2 For now, I see that caching is to blame. Even when I use NSURLCacheStorageNotAllowed, this code still tries to create cache dictionary, and write associated [UIApplication sharedApplication] into it.
2016-03-20 20:52:19.630 WebViewDemo[7102:663895] ADD: failed to create cache dictionary at path=/Users/xxx/Library/Developer/CoreSimulator/Devices/89D7C50F-939B-4360-A19F-4547AE4F7515/data/Containers/Data/Application/6F05411C-0261-4A33-9531-9E4E900C4910/Library/Caches/Test.WebViewDemo. key=0x7fe76af45f90
So, now next my question is - how can I disable this caching without implementing my own associated dictionary. Should I do that, or I simply should avoid setProperty:forKey:inRequest:.
And, most importantly, is that correct to use setProperty:forKey:inRequest: to store kOurRecursiveRequestFlagProperty, as Apple sample suggests? I'm still trying to figure out when I can use this methods, and when I can't.

IIRC, the reason why the data has to be plist-serializable is that in background tasks, URL requests are serialized and sent over XPC to a background daemon that actually performs the URL fetch. If the data weren't serializable, it would get lost in transit.
The objects you store here need to be small, self-contained pieces of data for the purposes of allowing your protocol to identify that request.
Typically, if you need to associate something more complex with a request, you would use this method to store a UUID or some other arbitrary string. Then you would store that same string as a key in a normal NSDictionary within your app, disposing of the dictionary key and associated data after you tell the client that the request has completed/failed.

Related

How do you return from an asynchronous NSURLConnection to the calling class?

I've got the following class which makes an HTTP post request asynchronously to avoid problems on the main UI thread:
#implementation DataFeeder
-(void) doLookup:(NSString *)inputValue
{
NSString *myRequestString = [NSString stringWithFormat:#"val=%#", inputValue];
NSMutableData *myRequestData = [ NSMutableData dataWithBytes: [ myRequestString UTF8String ] length: [ myRequestString length ] ];
NSURL * myUrl = [NSURL URLWithString: #"http://mywebsite/results.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: myUrl];
[request setHTTPMethod: #"POST"];
[request setHTTPBody: myRequestData];
[request setTimeoutInterval:10.0];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// Show error message
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// Use responseData
// Got all my response data here, so build up an object ready to send back
}
#end
I'm invoking the above from my ViewController using the following line of code :
MyObject * myObj = [feeder doLookup:#"SomeStaticStringForNow"];
So, this is how I understand it :
The doLookup will execute the request on an asynchronous
connection.
When the data has been fully loaded, it will invoke connectionDidFinishLoading
Once the data has finished loading, I will build up an object from the response data that I will send back to the calling controller
How can I have the calling controller listen out for this? Do I need to implement my own callback methods in the ViewController that will listen out for invocation and then stop a spinner and update the UI based on the contents of myObj ?
I'm hoping theres a really easy way that I've overlooked...
Thanks
Yeah, you should implement your callback using the delegate pattern. That is, in my opinion, the easiest and most standard way to do it. There are other ways, as you can see in the other responses.
In your DataFeeder.h file:
#protocol DataFeederDelegate
- (void)dataReady:(NSData*)data;
#end
#interface DataFeeder : NSObject {
id delegate_;
}
- (id)initWithDelegate:(id<DataFeederDelegate>)delegate;
#end
In your DataFeeder.m:
#implementation DataFeeder
- (id)initWithDelegate:(id<DataFeederDelegate>)delegate {
self = [super init];
if(self) {
delegate_ = delegate;
}
return self;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[delegate_ dataReady:responseData];
}
#end
You would instantiate a DataFeeder object like this:
DataFeeder *dataFeeder = [[DataFeeder alloc] initWithDelegate:self];
Of course, the calling view controller has to implement the DataFeederDelegate methods.
You have several approaches to getting you ViewController notified when the data is there:
define a delegate protocol between the ViewController and the DataFeeder, so that the latter sends a message to the former in connectionDidFinishLoading:;
use NSNotificationCenter so to decouple DataFeeder and ViewController: ViewController adds itself as an observer to the default notification center:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(dataIsThere:) name:kMyNetworkNotificationDataIsThere object:nil];
while DataFeeder send the notification at the right time:
[[NSNotificationCenter defaultCenter] postNotificationName:kMyNetworkNotificationDataIsThere object:self];
make ViewController implement the delegate methods for NSURLConnection and handle the response itself (this will require passing it as a parameter to DataFeeder constructor).
A nice way to do this would be using blocks. Your doLookup: method could accept a block object, and you can invoke that when the connection finishes.
Since you probably want to be able to perform multiple lookups with different completion blocks, you need to associate the passed in block with the appropriate NSURLConnection.
To do this ou can either use an NSURLConnection subclass with a completionBlock property, or use objective-C associated objects (by using the objc_setAssociatedObject and objc_getAssociatedObject functions) to attach the block to the connection object.
When everything is ready in the connectionDidFinishLoading: method and you've prepared the final response object, you grab the block from the NSURLConnection object and invoke it, passing it the final data.
So you eventually want your client code to look like this:
[feeder doLookup:#"Something" completionBlock:(FetchedData *data, NSError *error) {
if (error) {
// ...
return;
}
// access the returned data
}];
I hope this was enough detail for you.

Access Request Data sent, inside requestFailed Function ASIHttpRequest

How to access the (POST)data sent with the request from the requestFailed/requestFinished function.
- (void) abc {
NSString *postString = #"john";
NSURL *url = [NSURL URLWithString:#"http://abc.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setPostValue:postString forKey:#"name"];
[request setDelegate:self];
[request startAsynchronus];
}
- (void) requestFinished:(ASIHTTPRequest *)request
{
// Question is whether the request holds the sent post values.
// If it holds. how can we access them.
// i tried using [request valueForKey:#"name"];
// but it won't work.
}
Handling success and failure for multiple requests in delegate methods
If you need to handle success and failure on many different types of
request, you have several options:
If your requests are all of the same broad type, but you want to
distinguish between them, you can set the userInfo NSDictionary
property of each request with your own custom data that you can read
in your finished / failed delegate methods. For simpler cases, you can
set the request’s tag property instead. Both of these properties are
for your own use, and are not sent to the server.
If you need to handle success and failure in a completely different way for each
request, set a different setDidFinishSelector / setDidFailSelector for
each request For more complex situations, or where you want to parse
the response in the background, create a minimal subclass of
ASIHTTPRequest for each type of request, and override requestFinished:
and failWithError:.
That provided me a good solution to handle different requests.
You could try this -
- (void)requestFinished:(ASIHTTPRequest *)request {
NSLog(#"Response %d ==> %#", request.responseStatusCode, [request responseString]);
}
You can also handle other methods if you choose, such as:
- (void)requestStarted:(ASIHTTPRequest *)request;
- (void)requestFailed:(ASIHTTPRequest *)request;
The docs are located at http://allseeing-i.com/ASIHTTPRequest/ and are fantastic.
You can cast your request into a ASIFormDataRequest:
if ([request isKindOfClass:[ASIFormDataRequest class]]) {
ASIFormDataRequest *requestWithPostDatas = (ASIFormDataRequest *)request;
NSArray *myPostData = [requestWithPostDatas getPostData];
}
You will also have to make "postData" accessible with a "getPostData" public function in ASIFormDataRequest.

How to change JSON before mapping by RESTKIT

I am using RESTKIT to map the JSON returned from server.
The JSON result obtained from server is as follows
{"term":"Zh","results":{"users":[{"id":{"$oid":"4ebe59970a614e0019000055"},"term":"some text","score":1}]}
How can I convert the above JSON result to the below:
{"results":{"users":[{"uid":"4ebe59970a614e0019000055","text":"some text"}]}
Also, where can I do this so that the RESTKIT mapping will use the converted JSON instead of the initial one?
Below is the loader class that I am using to manage the JSON and mappings
-(void)getObjects
{
RKObjectManager *sharedManager = [RKObjectManager sharedManager];
[sharedManager loadObjectsAtResourcePath:self.resourcePath delegate:self];
}
- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response {
NSLog(#"Loaded PAYLOAD successfully for %#, with response %#", self.resourcePath , [response bodyAsString] );
}
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects
{
}
+ (void)setManagerAndMappings
{
RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:SERVER_URL];
RKObjectMappingProvider* provider = [[RKObjectMappingProvider new] autorelease];
//User Object Mapping
RKObjectMapping* userMapping = [RKObjectMapping mappingForClass:[User class]];
[userMapping mapKeyPath:#"_id" toAttribute:#"uid"];
[userMapping mapAttributes:#"avatar_url",#"created_at",#"email",#"name",#"nickname",#"follower_count",#"following_count",#"answer_count",#"new_notification_count",#"new_questions_count",#"is_following",#"facebook_configured",#"twitter_configured",#"description",#"approved",#"type", nil];
[provider setMapping:userMapping forKeyPath:#"user"];
}
#Shocks answer is appealing, unfortunately it is valid a for version before 0.20.
Anyway, a similar solution is available for 0.20 too, using an implementation of RKSerialization:
#interface ORRKJsonSerialization : NSObject <RKSerialization>
#end
and implementing
#implementation ORRKJsonSerialization
+ (id)objectFromData:(NSData *)data error:(NSError **)error
{
id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:error];
// change your data before mapping
return result;
}
+ (NSData *)dataFromObject:(id)object error:(NSError **)error
{
return [NSJSONSerialization dataWithJSONObject:object options:0 error:error];
}
#end
then during the setup:
[RKMIMETypeSerialization registerClass:[ORRKJsonSerialization class] forMIMEType:#"application/json"];
HTH
There is a willMapData: selector in the RKObkectLoaderDelegate that is invoked just after parsing has completed. The mappableData argumet is mutable, so i guess you can change the data just before the object mapping will take place.
use RKObjectRequestOperation.setWillMapDeserializedResponseBlock:.
In swift:
let request = RKObjectManager.sharedManager().requestWith...
let operation = RKObjectManager.sharedManager().managedObjectRequestOperationWithRequest(request, managedObjectContext: context, success: { operation, result in
// success
}, failure: { operation, error in
// failure
})
operation.setWillMapDeserializedResponseBlock { deserializedResponse -> AnyObject! in
// Here to transform response
return transformResponse(deserializedResponse)
}
RKObjectManager.sharedManager().enqueueObjectRequestOperation(operation)
For me the only solution is to modify the returned object at the server level.
If you can't,just map that returns the server.
You can register your own parser. I had to do this to modify and clean-up some JSON from a legacy system.
[[RKParserRegistry sharedRegistry] setParserClass:[MyJSONParser class]
forMIMEType:#"application/json"];
And then create your own:
#import <RestKit/RestKit.h>
#import <RestKit/RKJSONParserJSONKit.h>
#import <RestKit/JSONKit.h>
#import <RestKit/RKLog.h>
#interface EFJSONParser : RKJSONParserJSONKit
- (NSDictionary *)objectFromString:(NSString *)string error:(NSError **)error;
#end
It's very difficult to editing the response of JSOn. the better way is only to do changes in server side as said by #beber

RestKit: distinguish multiple requests in didLoadResponse:

I'd like to use RestKit and handle several different requests in the same class, i.e. in the didLoadResponse: method. How can I distinguish between the different requests? How do I know which request is finished?
I'm doing the request via
RKClient *client = [RKClient sharedClient];
[client get:#"/....", method] delegate:self];
Then, in the delegate-method
- (void)request:(RKRequest *)request didLoadResponse:(RKResponse *)response {
if (???) // request which gets XY returned
...
else if (???) // request which gets YZ returned
...
}
is that possible?
Sure, the RKClient get: method returns a RKRequest object. Just set a userData to the request and retrieve it later in the delegate.
RKClient *client = [RKClient sharedClient];
RKRequest *request = [client get:#"/....", method] delegate:self];
[request setUserData:#"FirstRequest"];
and check it later in the delegate
- (void)request:(RKRequest *)request didLoadResponse:(RKResponse *)response {
id userData = [request userData];
if ([userData isEqual:#"FirstRequest"]) // request which gets XY returned
...
else if (...) // request which gets YZ returned
...
}
This isn't an exact answer to your question, but I have the feeling that some people will come here wondering how to distinguish multiple requests in didLoadObjects, as I did. The solution is to use isKindOfClass.
For example, I make two HTTP calls when a user logs into my app, and I want to distinguish the object returned from the getUser call from the object returned by getSummary (because if I don't then it crashes). This code checks if the returned object is a "kind of" that particular class, and if so sets the object to a local instance of that object.
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
if ([[objects objectAtIndex:0] isKindOfClass:[APIUser class]]) {
APIUser *apiUser = [objects objectAtIndex:0];
}
else if ([[objects objectAtIndex:0] isKindOfClass:[APIUserSummary class]]) {
APIUserSummary *summary = [objects objectAtIndex:0];
}
}

More than one RKObjectManager at a time (RestKit)

I am testing out RestKit and need to access different BaseUrls and also sometimes access a web service with the same baseUrl from different places "at once", lastly I also need to access the same baseUrl with different ressourcePaths in the same controller.
In my app delegate I set up the RKObjectManager singleton like this.
RKObjectManager *objectManager = [RKObjectManager objectManagerWithBaseURL:kBaseUrl];
[objectManager registerClass:[EntityClass1 class] forElementNamed:#"element1"];
[objectManager registerClass:[EntityClass2 class] forElementNamed:#"element2"];
.
.
.
etc.
The singleton approach is really easy to work with, I however can't figure out how to separate the different web service calls.
In MyViewController, which implement the RKObjectLoaderDelegate, I will have the two methods:
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
//stuff with result
}
- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error {
//stuff with error
}
This causes no problems when MyViewController uses one RKObjectManager singleton to access one ressourcePath with one baseUrl.
If I start different requests in this way:
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:FLICKRPath delegate:self]
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:FOURSQUAREPath delegate:self]
and so on, within the same MyController, my problem is that FLICKRPath and FOURSQUAREPath of course has different baseUrl, but the RKObjectManager only has one?
If I get this working and can have different RKObjectManagers another problem arises.
The delegate methods didLoadObjects and didFailWithError will receive results from both RKObjectManagers and I can't see any other way to tell them apart than from their baseUrls. Potentially comparing each return value with a baseUrl and, even worse, a ressourcePath, in the delegate method does not appeal to me at all.
If I have different RKObjectManagers I guess I could pass them different delegates and build classes dedicated to deal with the return values from different baseUrls and ressourcePaths. This would mean I had to build yet another abstraction on top of MyController and RestKit, which also seems messy.
I have a strong feeling I am going about this in the wrong way, the RestKit source is very impressive which indicates that is me fighting the framework. I would really appreciate some best practice insights on the subject. I have been through all the resources and examples that I could find but have not seen the above use case. It is always one RKObjectManager, one baseUrl and one ressourcePath.
Thank you in advance.
Since there is no accepted answer yet: using multiple object managers is quite simple using RestKit.
From the Wiki (Using Multiple Base URLs (and Multiple Object Managers):
The first object manager you create will be the shared singleton
RestKit uses by default. But by creating additional object managers,
you can pull from their BaseURLs as needed, just be sure to retain
these new managers.
RKObjectManager *flickrManager =
[RKObjectManager objectManagerWithBaseURL:flickrBaseUrl]; // <-- shared singleton
RKObjectManager *foursquareManager =
[[RKObjectManager objectManagerWithBaseURL:foursquareBaseUrl] retain]; // <-- you must retain every other instance.
Depending on your application, you may want to put this second object
manager in a more accessible place, like a retained property on the
AppDelegate, so that it's easy to pull from as needed.
In the event that you need to differentiate between the results from
your two (or more) object managers, simply set an identifier in the
userData for the queries.
- (void)someAction(id)sender {
// .......
RKObjectLoader* loader = [[RKObjectManager sharedManager] loadObjectsAtResourcePath:#"/whatever" delegate:self];
loader.userData = #"foursquare";
// or do this, if you need a number instead of a string
loader.userData = [NSNumber numberWithInt:1234];
// .......
}
//Then when the delegate comes back you can cast it into a string or number as appropriate:
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
// .......
NSString* source = (NSString*) objectLoader.userData;
// or, if you did the NSNumber instead:
NSNumber* source = (NSNumber*) objectLoader.userData;
// .......
}
API change:
RKObjectLoader* loader = [[RKObjectManager sharedManager] loadObjectsAtResourcePath:#"/whatever" delegate:self];
doesn't compile in RestKit v.0.10.3 (loadObjectsAtResourcePath:delegate: returns void). That method just wraps a few lines of code, though, so you can still get at the loader, and add userData, with the following:
RKObjectLoader *loader = [[RKObjectManager sharedManager] loaderWithResourcePath:resourcePath];
loader.userData = #"SOMEDATA";
loader.delegate = self;
loader.method = RKRequestMethodGET;
[loader send];
(adding note in case other new users run into the same issues I did).
And by the way, since userData property is also available on RKRequest, you can use the same approach for loading/identifying requests.
For example, some post request:
RKClient * client = [RKClient sharedClient];
[client post:#"/your-api-path" usingBlock:^(RKRequest *request) {
request.userData = #"<some-object-you-can-check-in-delegate-callback>";
request.params = someParamsForRequest;
request.delegate = <delegate you want to call when request is finished>;
}];
How about using objectLoader.
You'll find the mapped object type/Class objectLoader.objectMapping.objectClass and add your conditions based on it instead of the url
-(void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
// your condition based on -> objectLoader.objectMapping.objectClass
}
Hope it will help
Possible approach is to introduce one singletone for each base url.
You can instantiate as many RKObjectManager objects as you want. However, only the first one will become shared. Look into initWithHTTPClient: sources.
if (nil == sharedManager) {
[RKObjectManager setSharedManager:self];
}
We can't use default sharedManager method to target specific object manager but we can easily implement our own singleton. Here's an example for Google Maps object manager:
#implementation GMObjectManager
+ (GMObjectManager*)sharedManager
{
static GMObjectManager *manager; // keep reference
if (!manager) {
// init with custom base url
NSURL *baseUrl = [NSURL URLWithString:kGMBaseUrl];
manager = [GMObjectManager managerWithBaseURL:baseUrl];
}
return manager;
}
- (id)initWithHTTPClient:(AFHTTPClient *)client
{
self = [super initWithHTTPClient:client];
if (self) {
// additional initialization
}
return self;
}
#end
Usage:
CGObjectManager *googleMapsManager = [GMObjectManager sharedInstance];