I'm new to objective-c and i'm having a hard time with a AFNetworking.
So the thing is that i want to make a simple POST request to a server who will send me back a salt.
I'v make a simple app, in order to test my request but i don't understand why i'm getting the error code 999.
Here a sample of my code.
+ (void)simpleRequest; {
NSURL *mailserver = [NSURL URLWithString:#"https://localhost:4443/"];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithBaseURL:mailserver];
manager.securityPolicy.allowInvalidCertificates = TRUE;
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = #{#"username": #"testtest"};
[manager POST:#"api/v0/login/salt" parameters:parameters success:^(NSURLSessionDataTask *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(NSURLSessionDataTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
I' have link this code to a simple Button which's calling this function.
I have an other app, in ruby motion which's work fined with this function i can get the response without any error. But with this simple app i can't do any request, they all returned this error code 999.
Error: Error Domain=NSURLErrorDomain Code=-999 "cancelled"
UserInfo={NSErrorFailingURLKey=https://localhost:4443/api/v0/login/salt,
NSLocalizedDescription=cancelled,
NSErrorFailingURLStringKey=https://localhost:4443/api/v0/login/salt}
So i'm really wondering what i'm doing wrong, anyone can help me on this ?
Thanks
EDIT:
Is it the good way for saving the manager in a property or am i doing something wrong ?
If it's the good way, this seems to not work
Thanks for the help
.h file
#property (nonatomic, retain) AFHTTPSessionManager *session;
.m file
#synthesize session;
- (IBAction)log:(id)sender {
NSURL *mailserver = [NSURL URLWithString:#"https://localhost:4443/"];
self.session = [[AFHTTPSessionManager alloc]initWithBaseURL:mailserver];
self.session.securityPolicy.allowInvalidCertificates = TRUE;
self.session.responseSerializer = [AFJSONResponseSerializer serializer];
self.session.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = #{#"username": #"testtest"};
[self.session POST:#"api/v0/login/salt" parameters:parameters success:^(NSURLSessionDataTask *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(NSURLSessionDataTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
In my case iOS 10 SDK's caused AFNetworking error code -999. If you're trying to reach a server that has SSL and you don't want to check it out, add some privacy Policy to Afnetworking
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = YES;
[securityPolicy setValidatesDomainName:NO];
That's error -999, not 999. That is NSURLErrorCancelled. Your request has been cancelled before it can be completed.
Looking at your code, you aren't retaining the AFHTTPSessionManager *manager anywhere. This means that the manager will be disposed as soon as +simpleRequest returns. I'm guessing that this is what is cancelling your request.
You need to save the manager so that it lives for the full duration of the request. Save it in a property somewhere.
In my case iOS 9 SDK's "App transport security" cause AFNetworking error code : -999.
If you're trying to reach a server that doesn't have a SSL add keys like screenshot below.
I noticed that your API endpoint indicates to a secure connection:
httpS://localhost:4443/api/v0/login/salt
Just try it just in case, maybe it repeats your situation.
In my case, this was a typo in the API manager code. Which from the part can be said is connected with App Transport Security Settings.
Just changed the protected protocol from httpS:// to http:// and the error:
NSURLErrorDomain Code = -999 "cancelled"
was gone and it all worked!
+And also if you had a similar problem. Be sure to discuss this with a backend specialist who deals with the server or API configuration for your application. This means that the server does not have valid security certificates. Perhaps you still need a secure connection. Or this specialist can again configure everything back from http:// to httpS://, and I'm not sure (did not check) whether this will work again when in the code you are already using a non-secure http:// connection.
[Original OP question may not mention Cordova but this link was very high in the search result when Googling this issue]
For my Cordova project (or similar), turns out it was a plugin issue. Make sure you're not missing any plugins and make sure they're installed properly without issue.
Easiest way to verify this is simply to start fresh by recreating the Cordova project (cordova create <path>) along with the required platforms (cordova platform add <platform name>) and add each plugin with the verbose flag (--verbose) so that you can see if anything went wrong in the console log while the plugin is being downloaded, added to project and installed for each platform (cordova plugin add cordova-plugin-device --verbose)
Recap:
cordova create <path>
cordova platform add <platform name>
cordova plugin add cordova-plugin-device --verbose
Related
I want to send max. 100 images in a single request to my server. Simple image upload works fine for me.
But I want to create a stream of data with AFNetworking 2.0 api. So, I want to ask that How I can create a newtwork stream with my image data.
Also, This stream should work in background mode of the app also & images should upload on the server in background mode of the app. How can I achieve this with AFNetworking 2.0 library?
Any suggestions will be helpful.
I do not think it is a good idea but I will answer your question to let you decide yourself.
AFAIK there are only two ways to send 100 images with a single request:
Bind them in a single file, for example zip them
Use multipart/form-data
First approach is quite obvious :) Let's talk about the second one.
Create a multipart request with AFNetworking:
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer]
multipartFormRequestWithMethod:#"POST"
URLString:[url absoluteString]
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
for (NSURL *imageUrl in imageURLsArray)
[formData appendPartWithFileURL:imageUrl name:[imageUrl lastPathComponent] error:nil];
}
error:nil];
Save request body to a file because background uploading is supported only for files, not for streams or data in a memory:
NSURL *fileURL = create url for a temporary file
[[AFHTTPRequestSerializer serializer]
requestWithMultipartFormRequest:request
writingStreamContentsToFile:fileURL
completionHandler:(void (^)(NSError *error))
{
NSMutableURLRequest *newRequest = [request mutableCopy];
newRequest.HTTPBodyStream = nil;
// Here you can start background uploading of file fileURL using newRequest request
}];
How to upload a file in background you can find for example here AFNetworking 2.0 and background transfers or here http://www.objc.io/issue-5/multitasking.html
I'd advise against a single request uploading 100 images because if it fails, the entire request fails. I'd be inclined to do individual requests. A single request may have an intuitive appeal because it is simpler, but it's going to be less graceful in the presence of network interruptions.
In terms of doing background uploads with AFNetworking, see AFNetworking 2.0 and background transfers, which walks through a few of the considerations (using AFHTTPSessionManager instead of AFHTTPRequestOperationManager, writing the necessary app delegate methods to capture background session completion handler, the fact that you cannot use task-specific completion block handlers, etc.).
Note, you will want to create upload tasks that upload a file. This means that if your web service is expecting a multipart/formdata request, that you should stage these requests to a file (see Avt's answer) and then supply that as the file parameter of the upload request. This not only is compatible with background sessions, but it has a minimal peak memory usage profile (which I assume was your intent behind your comment about wanting a stream-based request).
#Nirmit, you can upload larger number of images using multipart uploading. kindly followed the link. https://github.com/AFNetworking/AFNetworking.
while uploading set of images, you need to set timeout limit at your end as well as server end at max level. also you need to provide background running support. incase user enter in background mode.
In multipart request form:
you need to add for-loop of images instead of single image. here i added modification of multipart request form.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"foo": #"bar"};
[manager POST:#"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
for(int i=0:i<1000:i++){
NSURL *filePath = [NSURL fileURLWithPath:arrayImages[i]];
[formData appendPartWithFileURL:filePath name:#"image" error:nil];
}
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
I can't find easy answers on the web. I know that Social.framework is great for making things less complicated and less buggy. However I tried to implement like and failed - I don't think it is possible using only Social.framework. Now I'm trying to get some posts image and add a comment to it, it's also complicated, I'm not sure if possible. It seems all more complicated stuff you used to do via opengraph isn't possible with Social.framework.
Maybe there is a way to mix Social.framework with FacebookSDK and log user via the first framework and get object via 2nd with opengraph?
Can anyone write if these actions are possible? Or how to know what is possible/impossible with Social.framework? I consider mainly Facebook.
-- edit --
An example would be:
NSURL *likeUrl = [NSURL URLWithString:#"https://graph.facebook.com/me/og.likes"];
NSURL *objectUrl = [NSURL URLWithString:#"object_with_tags_to_like"];
NSDictionary *parameters = #{ACFacebookAppIdKey: #"111",
#"object": objectUrl};
SLRequest *facebookRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodPOST
URL:likeUrl
parameters:parameters];
facebookRequest.account = facebookAccount;
[facebookRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
// set a breakpoint here, we're getting in resp:
// "Www-Authenticate" = "OAuth \"Facebook Platform\" \"invalid_request\" \
// "The action you're trying to publish is invalid because it does not specify any reference objects.
// At least one of the following properties must be specified: object.\"";
}];
Here we can see that passing object isn't easy. With FacebookSDK you'd simply:
NSMutableDictionary<FBGraphObject> *action = [FBGraphObject graphObject];
action[#"object"] = urlAddress;
[FBRequestConnection startForPostWithGraphPath:#"me/og.likes"
graphObject:action
completionHandler:nil];
But here you can't create FBGraphObject. What to use instead?
Honestly the Facebook SDK is quit powerful and simple to use. It allows you much more functionality in terms of Liking and Commenting so I would recommend you move towards that. The SocialFramework is limited, it is mainly used for sending a quick post (using their template, -> no customization) and quick login.
I have successfully done all of what you are asking for using solely the Facebook SDK.
I am creating an App for iOS/Andriod using appery.io (basically a phonegap type website that uses a WYSIWYG) that will basically be a calendar for upcoming TV episodes. Users will select the shows they want to watch and the calendar/list in the App will be populated with the upcoming episodes.
For this, I am trying to use an api called thetvdb.com. However, I have only basic knowledge of databases and even less with API usage. Thetvdb has some documentation for using their API, however, it is difficult to understand and translate into the appery.io form I am using to get requests.
Using their API requires a key, which I already have. I am just not sure what to put for the settings, and request fields. The main one I need to figure out is the URL under settings first. Any help would be greatly appreciated!
Settings:
URL:
Method:
Data Type:
Content Type:
Request:
Not even sure what parameters to use.
Thetvdb.com Documentation (http://www.thetvdb.com/wiki/index.php/Programmers_API)
The appery.io video tutorial I am following (http://www.youtube.com/watch?v=d_iGKRPPsRc&list=PLdUnWwhvJspZXXuozUbly21FBh9AywSa6)
You can using AFNetworking framework. It is easy to use for communication with API.
With GET method, we can do:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"http://example.com/resources.json" parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
For more information, please read on this website.
https://github.com/AFNetworking/AFNetworking
I'm interested in integrating the Imgur API into my app, and it states that in order to get image information (basically the extent of what I need right now) I just need to register my app, no need to log in with user information or anything.
Great, I'm using AFOAuth2Client (specifically this pull request so it works with AFNetworking 2.0). I have my client key and client secret, but I can't seem to figure out how to get to an image.
I try the following code (personal API details removed):
AFOAuth2Client *oauthClient = [AFOAuth2Client clientWithBaseURL:[NSURL URLWithString:#"https://api.imgur.com/"] clientID:#"---" secret:#"---"];
[oauthClient authenticateUsingOAuthWithURLString:#"https://api.imgur.com/oauth2/authorize" parameters:nil success:^(AFOAuthCredential *credential) {
NSLog(#"Yes");
} failure:^(NSError *error) {
NSLog(#"No");
}];
But I always get No outputted. How do I properly authenticate so I can then make calls to the API to get information about an image? (As detailed here.)
As I've been told I don't need OAuth period, I tried the following with AFNetworking 2.0 (to no avail):
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
[operationManager POST:#"https://api.imgur.com/3/image/1Nf1quS" parameters:#{#"Authorization": #"Client-ID myactualclientidisremoved"} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"failure");
}];
First, the example is using Imgur API v2 which is old and unsupported. You should be using API v3.
Also note that:
For public read-only and anonymous resources, such as getting image info, looking up user comments, etc. all you need to do is send an authorization header with your client_id in your requests.
from docs at https://api.imgur.com/oauth2 -- so you don't really need OAuth for what you're doing.
There is some example Imgur API code that might help you, listed at https://api.imgur.com/ -- the Android example might be more relevant to you, since it uses Java, but unsurprisingly it comes with all the overhead of an Android project, compared with a plain Java application.
I'm using AFNetworking in my app to connect / download data from a web service. This app is deployed via Enterprise deployment to users at various locations. At one of the locations where people use our app, the wifi network seems to randomly go down / come back up in a few seconds. In these cases, the requirement was to retry a request thrice before giving up and failing. I've got the retry part of it working fine, but have some problems detecting a network failure. Some code:
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation *operation, id responseObject) {
[self parseResponse:operation.responseString];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self messageFailureWithCode:error.code
reason:[NSString stringWithFormat:#"%#", error]];
}
];
The error code I'm retrying on is NSURLErrorTimedOut. But I just got another log file which indicated a failure with the following error: -1003 "A server with the specified hostname could not be found."
I could add this code to my list too, but I wanted to be sure that I'm capturing all the errors and not just handling them as they appear. I was looking through the NSURLError.h file and found the following error codes that vaguely look like they could be caused by a network failure.
Can someone help me figuring out under what conditions each error is triggered and if I'm missing any error codes? The list is below:
NSURLErrorCannotFindHost
NSURLErrorTimedOut
NSURLErrorCannotConnectToHost
NSURLErrorNetworkConnectionLost
NSURLErrorDNSLookupFailed
NSURLErrorResourceUnavailable
NSURLErrorNotConnectedToInternet
Thanks,
Teja.
It sounds like you could safely just retry every failure with an error domain of NSURLErrorDomain (exempting the case where an operation was cancelled). That should cover all of those cases.