How to Post data in iOS? - ios

I am doing an instagram appliaction. In that I need to post like on Images. I am not able to post . I am following instgram API. We need to use following url
https://api.instagram.com/v1/media/{media-id}/likes
We need to set media id like
https://api.instagram.com/v1/media/649114513807113248_1032025382/likes
media id = 649114513807113248_1032025382
My code to post:
NSString *urlString = [NSString stringWithFormat:#"https://api.instagram.com/v1/media/649114513807113248_1032025382/likes"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
NSURLConnection *connection= [[NSURLConnection alloc] initWithRequest:request
delegate:self];
[connection start];
But like is not posting. Can anyone help me ?

You can post your data in better way using AFNetworking framework. Samples are also provided on github.
http://afnetworking.com/

MGInstagram and DMActivityInstagram is a iOS Utility for posting Images to Instagram from your app.
// Uses our instagram instance to do a request
- (void) postMessage:(NSString *)message mediaId:(NSString *)mediaId {
NSString* methodName = [NSString stringWithFormat:#"media/%#/comments", mediaId];
NSMutableDictionary* params = #{"text" : message};
[m_instagram requestWithMethodName:methodName params:params httpMethod:#"POST" delegate:self];
}
// IGRequestDelegate method that is called once we get a response
- (void)request:(IGRequest *)request didLoad:(id)result {
// post message was ok
}
- (void)request:(IGRequest *)request didFailWithError:(NSError *)error {
// post message fails
}
Reference from https://github.com/crino/instagram-ios-sdk/issues/27
if you are share the images to social network use below link it have sample app with tutorial
share-an-image-on-instagram-in-ios/

better to use AFNetworking for post, bellow is a sample , please have a look
-(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock
{
NSMutableURLRequest *apiRequest =
[self multipartFormRequestWithMethod:#"POST"
path:kAPIPath
parameters:params
constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
//TODO: attach file if needed
}];
AFJSONRequestOperation* operation = [[AFJSONRequestOperation alloc] initWithRequest: apiRequest];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//success!
completionBlock(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//failure :(
completionBlock([NSDictionary dictionaryWithObject:[error localizedDescription] forKey:#"error"]);
}];
[operation start];
}

Related

AFNetworking fails to create a request on a GET request

I'm trying to make a get request to a restful service. This request has worked for the last 3 weeks when I was using a request without a request manager. As soon as I added a request manager because I wanted to send a dictionary of parameters, the code keeps crashing with the error:
'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: urlRequest'
My code is as follows. The commented out code still works if I uncomment it and replace the new code with it. Why am I able to make a request from that URL but not with AFNetworking?
NSString *URLForSend = [NSString stringWithFormat:#"%#%#/", ([_remoteDownloadURLString stringByAppendingString:_getFilesJsonURLString]),_userName ];
NSURL *URL = [NSURL URLWithString:URLForSend];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
self.downloadJsonRequest = [[AFHTTPRequestOperation alloc] initWithRequest:request];//this works to create a a afhttprequestoperation, with the same url
_downloadJsonRequest.responseSerializer =
[AFJSONResponseSerializer serializerWithReadingOptions: NSJSONReadingMutableContainers];
__unsafe_unretained typeof(self) weakSelf = self;
NSMutableDictionary *mutDictForSend = [[NSMutableDictionary alloc] initWithDictionary:[[NSUserDefaults standardUserDefaults] objectForKey:#"tokenInfo"]];
[mutDictForSend removeObjectForKey:#"success"];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] init];
[manager GET:URLForSend parameters:mutDictForSend success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"%#", responseObject);
weakSelf.jsonArrayForCaching = responseObject;
[[NSNotificationCenter defaultCenter] postNotificationName:kBIDContentEndingSync object:weakSelf];
[weakSelf gotNewJson:responseObject];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Request Failure Because %#",[error userInfo]);
}];
/*
[_downloadJsonRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"%#", responseObject);
weakSelf.jsonArrayForCaching = responseObject;
[[NSNotificationCenter defaultCenter] postNotificationName:kBIDContentEndingSync object:weakSelf];
[weakSelf gotNewJson:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Request Failure Because %#",[error userInfo]);
}];
[[NSNotificationCenter defaultCenter] postNotificationName:kBIDContentStartingSync object:self];
[_downloadJsonRequest start];
*/
I'd suggest replacing the line:
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] init];
With
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
The latter calls initWithBaseURL, which does some configuration of the AFHTTPRequestOperationManager, that just calling [[AFHTTPRequestOperationManager alloc] init] does not appear to do.
If you're still having issues even doing that, I'd suggest adding Exception Breakpoint to identify precisely where this exception is taking place.
OK, this was a tough one, but it turns out that requestOperationManager is a singleton so I should not have initialised him, but call its instance...

Uploading images to server

I am trying to upload an image to a server (that is already built) and I am getting errors like Request has timed out. Other methods of sending text and fetch data from the server are working properly. However, sending an image I found it hard to do it.
I am using the following code at the moment:
-(void)uploadImage:(NSData*)image callbackBlock: (void (^)(BOOL success)) callbackBlock
{
NSString *path = [NSString stringWithFormat:#"upload"];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:image, #"image", nil];
[params addEntriesFromDictionary:self.sessionManager.authParameters];
NSMutableURLRequest *request = [self multipartFormRequestWithMethod:#"POST" path:path parameters:params constructingBodyWithBlock: ^(id <AFMultipartFormData>formData){
[formData appendPartWithFormData:image name:#"Image"];
}];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"!!!Response object: %#",responseObject);
callbackBlock(YES);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#",error.description);
callbackBlock(NO);
}];
[self enqueueHTTPRequestOperation:operation];
}
Do you have any idea what the problem is? Can you give me some suggestions or possible errors on the above code.
Thank you very much.
You can send your image as a base64 encoded text... This should work.
You can use this category to create base64 encoded image:
https://github.com/l4u/NSData-Base64

Upgrading to AFNetworking

I am taking over an old iOS project from developers no longer part of the project - the app is getting a rewrite and with that I am going to support iOS7 and upwards only.
So, I wanted to use AFNetworking 2.0 instead of ASIHTTPRequest - the reason behind this is NSURLSeesion. AFNetworking 2.0 supports NSURLSession and with that I can get my app to download content in the background at opportunistic times (According to Apple - NSURLSession must be used and Background Fetch mode turned on, for this to work? )
Let me start out by saying I am a new developer to iOS and networking stuff goes a little over my head - but I am determined to learn more about it and as much as I can. I have read AFNetworking documentation as well, but I fear since some of the terminology escapes me (Request, Response, Sterilisation, etc) - I am not grasping them 100%.
So, I took a look at the ASIHTTPRequest code the previous developer used to, from what I can see, build a GET / POST request - This is the code they used:
+ (ASIHTTPRequest*) buildRequest: (NSString*) url RequestType: (NSString*) requestType
PostData: (NSString*) postData
Host: (NSString*) host
ContentType: (NSString*) contentType
SoapAction: (NSString*) soapAction
RequestProperties: (NSDictionary*) requestProperties
{
NSURL *url = [NSURL URLWithString: url];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:u] autorelease];
[request setDidFinishSelector:#selector(requestDone:)];
[request setDidFailSelector:#selector(requestWentWrong:)];
[request setTimeOutSeconds:20];
[request setQueuePriority:NSOperationQueuePriorityVeryHigh];
if (host != nil)
[request addRequestHeader: #"Host" value: host];
if (contentType != nil)
[request addRequestHeader: #"Content-Type" value: contentType];
if (soapAction != nil)
[request addRequestHeader: #"SOAPAction" value:soapAction];
if (requestType != nil)
[request setRequestMethod: requestType];
if (postData != nil)
{
NSMutableData* mPostData = [NSMutableData dataWithData:[postData dataUsingEncoding:NSUTF8StringEncoding]];
NSString *msgLength = [NSString stringWithFormat:#"%d", [postData length]];
[request setPostBody: mPostData];
[request addRequestHeader: #"Content-Length" value:msgLength];
}
if (requestProperties != nil)
{
for (int i = 0; i < [[requestProperties allKeys] count]; i++)
{
[request addRequestHeader:[[requestProperties allKeys] objectAtIndex: i] value: [requestProperties objectForKey:[[requestProperties allKeys] objectAtIndex: i]]];
}
}
return request;
}
I'm trying to understand this code and upgrade it to use AFNetworking V2.0 instead. I assume, just replacing ASIHTTPRequest with AFHTTPRequestOperation will not do the trick, correct?
I have been given some help and also managed to do a lot of digging around to see how I can get this right.
I made the method simpler - as I did not need Soap / Content-type, etc - just urlParamerters and some basic stuff:
This is the answer I came up with:
+ (AFHTTPSessionManager *) buildRequest: (NSString*) url RequestType: (NSString*) requestType PostDataValuesAndKeys: (NSDictionary*) postData RequestProperties: (NSDictionary*) requestProperties
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
if ([requestType isEqualToString:#"GET"])
{
[manager GET:url parameters:postData success:^(NSURLSessionDataTask *dataTask, id responseObject){
//Success
NSLog (#"Success");
NSData *xmlData = responseObject;
NSLog(#"Got XML Data: %#", xmlData);
}
failure:^(NSURLSessionDataTask *dataTask, NSError *error){
//Failure
NSLog (#"Failure");
}];
}else if ([requestType isEqualToString:#"GT"]){
[manager POST:url parameters:postData success:^(NSURLSessionDataTask *dataTask, id responseObject){
//Success
}
failure:^(NSURLSessionDataTask *dataTask, NSError *error){
//Failure
NSLog (#"Failure");
}];
}
return manager;
}
It will work for what I need it to do - but I am not sure if it's the best way to do it.
I couldn't see how I could detect the requestType other thank with looking at the NSString value. I looked into the AFHTTPSessionManager.h file for some clues on what to do with that - Matt suggests overriding the GET / POST methods if I want them done differently - per his comments in the header file:
Methods to Override
To change the behavior of all data task operation construction, which
is also used in the GET / POST / et al. convenience methods,
override dataTaskWithRequest:completionHandler:.
Also there is a requestSerializer property in that file - which you could use to detect the type of request - however it's implementation goes to the super class: AFURLSessionManager
In that class - there is a requestWithMethodmethod.
So, I tried to do this instead:
If I try implement that method - then I am not using the convince methods in AFHTTPSessionManager:
(NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(NSDictionary *)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
Unless I have that completely wrong. After that I decided to just check the requestType using [NSString isEqualToString]

AFJSONRequestOperation not working (postpath works)

I am trying to post a JSON using AFNetworking.
Here's the code that im using:
+ (RESTAPI *)sharedClient
{
static RESTAPI *_sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:#"https://mybaseurl.com"]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url
{
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self setParameterEncoding:AFJSONParameterEncoding];
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:#"Accept" value:#"application/json"];
[self setAllowsInvalidSSLCertificate:YES];
return self;
}
The following code does not works. Everytime i try i get the following error:
The operation couldn’t be completed. (NSURLErrorDomain error -1012.)
// this code does not works
//
- (void)loginNOTWORKING
{
RESTAPI *client = [RESTAPI sharedClient];
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
[[AFNetworkActivityIndicatorManager sharedManager] incrementActivityCount];
NSDictionary *parameter = #{#"tgout": #"1",
#"tgin": #2,
#"username": #"foo",
#"password":#"bar"};
NSURLRequest *request = [client requestWithMethod:#"POST" path:#"/login" parameters:parameter];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// code for successful return goes here
[[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount];
NSLog(#"THIS IS NEVER CALLED: %#", JSON);
// do something with return data
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
// code for failed request goes here
[[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount];
NSLog(#"SAD, VERY SAD: %#", error.localizedDescription);
// do something on failure
}];
[operation start];
}
This code works:
// this code WORKS
- (void)loginWORKING
{
RESTAPI *client = [RESTAPI sharedClient];
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
[[AFNetworkActivityIndicatorManager sharedManager] incrementActivityCount];
NSDictionary *parameter = #{#"tgout": #"1",
#"tgin": #2,
#"username": #"foo",
#"password":#"bar"};
[client postPath:#"/login" parameters:parameter success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Print the response body in text
NSLog(#"IT WORKS: %#",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Response: %#", error.localizedDescription);
}];
}
Why the first login method does not works? What am i doing wrong?
Try by replacing
NSURLRequest *request = [client requestWithMethod:#"POST" path:#"/login" parameters:parameter];
with
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"/*HERE THE URL STRING TO CALL*/"]]
You can find the error -1012 in file CFNetworkErrors.h:
kCFURLErrorUserCancelledAuthentication = -1012
"The connection failed because the user cancelled required authentication."
I guess, there is an issue with your authentication. The error description is possibly misleading with regard to "the user" - it is actually a delegate method that gets invoked which cancels the authentication, or the authentication simply fails.
This of course can be caused by not properly serializing the parameters. I would suggest to use a lower level API, create the request manually, encode the JSON manually with NSJSONSerialization, and set the body data and the URL of the request. IMHO, this is certainly more readable code, and likely requires less code.

How to do HTTPS GET request AFNetworking

This is the method I use to do HTTP GET request. How can I change it to use HTTPS?
AS_NET_BASE_URL = http://www.myapp.com
Is it just as simple as replacing the http:// with https:// ?
Thank you in advance
+(void)startGETRequestAtUrlRoute:(NSString *)route withParameters:(NSString *)slashSeparatedParams completion:(void (^)(BOOL, id))completion{
//If internet is rachable, start request
if ([self isInternetReachable]) {
//Where request is going
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:AS_NET_BASE_URL]];
NSString *path = [NSString stringWithFormat:#"%#%#%#", AS_NET_BASE_URL, route, slashSeparatedParams];
//Tell operation to expect JSON
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
//Start spinner
[self startNetworkIndicator];
//Set up actual GET request
[httpClient getPath:path
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
//Stop spinning
[self stopNetworkIndicator];
//Make the response JSON valid
if (responseObject) {
completion(YES, responseObject);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self stopNetworkIndicator];
completion(NO, NULL);
//Error
NSLog(#"%#", error);
}
];
//No internet connection
}else{
completion(NO, NULL);
}
}
Yes.
HTTP/HTTPS is determined by the scheme of the URL, which in your case is specified in AS_NET_BASE_URL.

Resources