Load image with headers and cache it - Objective-C (macOS apps) - ios

I need to load big image from thumbnail url with forHTTPHeaderField and cache it so that not to load again and again from url. Below is the code I am using.
NSString *urlStr = [NSString stringWithFormat:#"%#",medialurl];
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"GET"];
[request setURL:url];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"abcd" forHTTPHeaderField:#"ABC"];
[request addValue:#"xyzzy" forHTTPHeaderField:#"XYZ"];
[RestService fetchDataWithCompletionBlock:request completionHandler:^(NSData * _Nonnull responseData, NSURLResponse * _Nonnull response, NSError * _Nonnull error) {
NSString *responseStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"responseStr: %#", responseStr);
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
long code = (long)[httpResponse statusCode];
NSLog(#"response status code: %ld", code);
completionBlock(responseData);
}];

Would setting a different cachePolicy on your request help?
request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
Use existing cache data, regardless or age or expiration date, loading from originating source only if there is no cached data.
There is a note on the cachePolicy property which states:
This property is ignored for requests used to construct NSURLSessionUploadTask and NSURLSessionDownloadTask objects, as caching is not supported by the URL Loading System for upload or download requests.
So, if that is how you're performing your request, this might not work and you would probably have to manage your caching for this request yourself.
You can check to see if there is a cached response for your request with the following (assuming you are using the shared cache and not creating your own):
NSCachedURLResponse* cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
if ( cachedResponse )
{
NSHTTPURLResponse* response = (NSHTTPURLResponse*)cachedResponse.response;
NSLog(#"Cached Response: %#", response.allHeaderFields);
}
else
{
NSLog(#"No Cached Response");
}
If your endpoint uses ETags, you can also store the value of the ETag header field from the cached response and then compare it to what you get back when you make your request, this would tell you if the response you get back was indeed from the cache or not.
If the above tells you there is no cached response for your request, then you'd have to look into why it might not be caching previous responses. Perhaps there is an issue with the "Cache-Control" header coming back from the server and you are not permitted to cache the responses? If that were the case and you have no control over the server side, you would have to use another method to cache your images.

Related

SOAP services iOS

I wanted to call SOAP services, saw many document's over link.
I used one of those like the BestSoaptool from github https://github.com/yillars/BestSoapToolwithafnet, but I am still lacking some where and not able to get the response.
I am using the link as -- "https://aaa.com/Customers.svc?singleWsdl" and then the method name "xxx" but I don't get a response.
If not this can any one give me some better idea as to how should I implement this?
Thanks.
I've added sample SOAP implementation in iOS in my wordpress blog. Hope this will help you https://wordpress.com/post/bharathreddys.wordpress.com/6
Lets assume the following .wsdl url is the source URL.
http://www.webservicex.net/geoipservice.asmx?WSDL
Create a SOAP Envelop and SOAP Header.
NSMutableString * soapHeader = #"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\""
" xmlns:hom=\"http://www.webservicex.net/">"
"<soapenv:Header/>";
Be remember that "xmlns:hom", text next to ":" is the word which will be used as the targetnamespace reference for the service call which will be added in SOAP body.
SOAP body will be as follows :
[soapHeader appendString:#"<soapenv:Body>"];
[soapHeader appendString:#"<hom:GetGeoIP>"]; // add the body parameters
[soapHeader appendString:#"<hom:IPAddress>0.0.0.1</hom:IPAddress>"];
[soapHeader appendString:#"</hom:GetGeoIP>"];
[soapHeader appendString:#"</soapenv:Body>"];
[soapHeader appendString:#"</soapenv:envelope>"];
Now the web service is as follows:
NSMutableString * requestStr = [NSMutableStringstring];
[requestStr appendString:soapHeader];
NSString * urlStr = #"http://www.webservicex.net/geoipservice.asmx?WSDL";
NSURL * url = [NSURL URLWithString:urlStr];
NSMutableURLRequest * request = [[NSMutableURLRequestalloc] initWithURL:url];
[request setValue:#"http://www.webservicex.net/GetGeoIP" forHTTPHeaderField:#"SOAPAction"];
[request setValue:#"http://www.webservicex.net/" forHTTPHeaderField:#"targetNamespace"];
[request setValue:#"text/xml;charset=UTF-8"forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:requestBody];
[request setHTTPMethod:#"POST"];
[request setValue:[NSStringstringWithFormat:#"%d",[requestBody length]] forHTTPHeaderField:#"Content-Length"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
BOOL isSuccess = YES;
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(#"received data---%#",response);
if(connectionError != nil) {
isSuccess = NO;
NSLog(#"connection error with code %d",connectionError.code);
}
NSDictionary * responseDictionary = [NSDictionary dictionary];
if([httpResponse statusCode] == 200) {
isSuccess = YES;
//Do something with the received dictionary.
}];
This is the basic platform how we can make a simple SOAP based web service calls in iOS.
Happy coding !!!!

Get external player URL from Vimeo api for tvOS

I want to use vimeo to host videos for a AppleTV app. I realise I will need a pro account to do exactly what I want, but at the moment just trying to do a POC.
What I need to achieve is to retrieve a url of my private video that expires after 1 hour, and I want the app to be authenticated with my credentials, not having the user have to sign in (as if the have the app, then they can view the videos).
Code that I am using is below, the constants set are:
kVimeoToken is an access token I created on vimeo for the app, and I have imported the vimeo api into my project.
-(NSString*) getVimeoUrls2 {
VIMClient *client = [[VIMClient alloc] initWithDefaultBaseURL];
AFJSONRequestSerializer *serializer= [AFJSONRequestSerializer serializer];
NSString *token = kVimeoToken;
//[serializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[serializer setValue:#"application/vnd.vimeo.*+json; version=3.2" forHTTPHeaderField:#"Accept"];
[serializer setValue:[NSString stringWithFormat:#"Bearer %#", token] forHTTPHeaderField:#"Authorization"];
client.requestSerializer = serializer;
__block NSString *str= nil;
[client requestURI:#"/me" completionBlock:^(VIMServerResponse *response, NSError *error)
{
id JSONObject = response.result;
NSLog(#"JSONObject: %#", JSONObject);
NSLog(#"Error: %#", [error localizedDescription]);
str = [[NSString alloc] initWithData:JSONObject encoding:NSUTF8StringEncoding];
}];
return str;
}
All I get back is an empty string, any idea what I am doing wrong?
If I change the access token so it is incorrect then I get back an error message {"error":"You must provide a valid authenticated access token."}, so it appears that I get authenticated ok. I have also tried some other endpoints but all of them end up with an empty string.
I have tried two separate approaches, both with the same result...i.e none, or an empty string.
I posted the question on the vimeo forums and got provided these two links:
developer.vimeo.com/api/authentication#single-user
github.com/vimeo/VIMNetworking#lightweight-use
The is the output from the log for the above code is below:
2016-01-09 08:13:26.091 tvOSShortGame[68357:91090409] server start (/me/watched/videos)
2016-01-09 08:13:26.461 tvOSShortGame[68357:91090448] server success 0.370109 sec (/me/watched/videos)
..and if I change the endpoint to /xxx (to force an error)
2016-01-09 08:07:28.826 tvOSShortGame[67829:91039056] server start (/xxx)
2016-01-09 08:07:29.003 tvOSShortGame[67829:91039045] server failure 0.177531 sec (/xxx)
2016-01-09 08:07:29.003 tvOSShortGame[67829:91039460] JSONObject: (null)
2016-01-09 08:07:29.003 tvOSShortGame[67829:91039460] Error: Request failed: not found (404)
Other endpoints get the same result, reports success but there is no JSON object returned.
Any help appreciated.
I finally got this working by using Postman which I saw on one of the Vimeo forums. It produces the correct code in multiple languages, and shows the resulting JSON so you can validate your endpoints.
Hope someone finds it useful.
//Obj C version
NSDictionary *headers = #{ #"authorization": #"Bearer MY_VIMEO_TOKEN",
#"cache-control": #"no-cache",
#"postman-token": #"MY_POSTMAN_TOKEN" };
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://api.vimeo.com/videos/116999999"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:#"GET"];
[request setAllHTTPHeaderFields:headers];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"%#", error);
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSLog(#"%#", httpResponse);
}
}];
[dataTask resume];
//Swift version
let headers = [
"authorization": "Bearer MY_VIMEO_TOKEN",
"cache-control": "no-cache",
]
var request = NSMutableURLRequest(URL: NSURL(string: "https://api.vimeo.com/videos/116999999")!,
cachePolicy: .UseProtocolCachePolicy,
timeoutInterval: 10.0)
request.HTTPMethod = "GET"
request.allHTTPHeaderFields = headers
var str = ""
let session = NSURLSession.sharedSession()
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error)
} else {
let httpResponse = response as? NSHTTPURLResponse
str = self.parseJSON(data!)
}
})
dataTask.resume()

IOS: Check existence of remote file

Is there any resource efficient way (something that does not tie up the main thread) in IOS to check the existence of a remote file?
I have user images stored on a server. While there is a consistent url scheme, some images are .jpg, others are .gif, etc. so to get the correct image name, I need to check does user/file.gif exist, user/file.jpg exist etc. in order to download the file to the IOS app.
I found this code in another answer in IOS
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"HEAD"];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
But I am not sure how to use it. Ideally, I would like to get a boolean yes or no as to whether the .gif file exists, the .jpg file exists etc for the users profile pic so I can fill in the correct name to download the user pic.
The alternative would be to write a service on the back end to return the file but wondering if it can all be done in IOS.
Thanks for any suggestions.
**Use this function below to check whether file exists at specified url**
+(void)checkWhetherFileExistsIn:(NSURL *)fileUrl Completion:(void (^)(BOOL success, NSString *fileSize ))completion
{
//MAKING A HEAD REQUEST
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileUrl];
request.HTTPMethod = #"HEAD";
request.timeoutInterval = 3;
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
if (connectionError == nil) {
if ((long)[httpResponse statusCode] == 200)
{
//FILE EXISTS
NSDictionary *dic = httpResponse.allHeaderFields;
NSLog(#"Response 1 %#",[dic valueForKey:#"Content-Length"]);
completion(TRUE,[dic valueForKey:#"Content-Length"]);
}
else
{
//FILE DOESNT EXIST
NSLog(#"Response 2");
completion(FALSE,#"");
}
}
else
{
NSLog(#"Response 3");
completion(FALSE,#"");
}
}];
}

Send request to server iOS

I am trying to figure out how to send data to the server but currently without any progress.
What I know
On the server I have got some php script that return me data in response
for example with this URL: http://test.com/mobile_api/register
this script get next parameters:
id
name
info
time
so the string which I need looking like below
http://test.com/mobile_api/register?id=1000&name=alex&info=1.0&time=10000
What is best way to send this is string on the server
Now I'm trying to use ASIHTTPRequest. Can anybody send an example how to create correct request with my parameters.
This sample code should help you
-(void)sendRequest
{
int userId=10, time=10000;
NSString *name = #"ABC";
float info = 1.0;
NSString *urlString = [NSString stringWithFormat:#"http://test.com/mobile_api/register?id=%d&name=%#&info=%f&time=%d",userId,name,info,time];
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
//You need to add ASIHTTPRequestDelegate in header(.h) file
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}

iOS application connect to .NET Webservice by GET method

everyone! My english is poor and sorry fot that.
I want implement a function in my test iOS application.
There is a .NET Webservice API just like
"https://xxx.xxx.xx.xxx/FMS/Pages/Service/FMService.svc/Login"
I want to connect the API with two parameters:user and pass
using the GET method,and the url will be like:
"https://xxx.xxx.xx.xxx/FMS/Pages/Service/FMService.svc/Login?user=xxx&pass=xxx"
if login, the Webservice will return a JSON value just like {"d":"success"}
if not, it will also return a JSON value like {"d":"failure"}
I am using the ASIHTTPRequest framework and JSON framework
I dont know how to implement the function. So please help me, thanks a lot.
Best wishes!
NSURL *url = [NSURL URLWithString:#"https://192.168.1.245/FMS/Pages/Service/FMService.svc/Login?user=jiangxd&pass=123456"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request addRequestHeader:#"Accept" value:#"application/json"];
[request addRequestHeader:#"Content-Type" value:#"application/json"];
[request setRequestMethod:#"GET"];
[request setDelegate:self];
[request startAsynchronous];
NSString *responseString = [request responseString];
NSDictionary *responseDict = [responseString JSONValue];
NSString *unlockCode = [responseDict objectForKey:#"d"];
NSLog(#"%#",unlockCode);
The unlockCode is always null... and I dont understand why!
NSURL *url = [NSURL URLWithString:#"https://192.168.1.245/FMS/Pages/Service/FMService.svc/Login?user=jiangxd&pass=123456"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSError *error = [request error];
if (!error)
{
NSString *responseString = [request responseString];
NSDictionary *responseDict = [responseString JSONValue];
NSString *unlockCode = [responseDict objectForKey:#"d"];
NSLog(#"%#",unlockCode);
}
else
{
NSLog(#"%#",[error description]);
}
And now I change startAsynchronous to startSynchronous but there is also an error:
Error Domain=ASIHTTPRequestErrorDomain Code=1 "A connection failure occurred: SSL problem (Possible causes may include a bad/expired/self-signed certificate, clock set to wrong date)" UserInfo=0x6b81640 {NSUnderlyingError=0x6b811b0 "The operation couldn’t be completed. (OSStatus error -9807.)", NSLocalizedDescription=A connection failure occurred: SSL problem (Possible causes may include a bad/expired/self-signed certificate, clock set to wrong date)}
NOTICE:The url is https, not http!(Is this the reason that I get an error?)
But if I access the url directly with browser, the Webservice will return the right value...
Thank you!
You should probably try it, and then post your code. You're asking someone to write this entire function for you, and I don't think that that is the purpose of this site.
Secondly, the developer behind the ASIHTTPRequest is no longer supporting it. Unless the community picks up, you might want to just learn how to do NSURLConnections from scratch.
Edit: There we go. So, you're doing this asynchronosly which means that when you start it, you're not immediately going to have the response. Have you setup your callbacks to process the response?
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}

Resources