iOS MKTileOverlay with self signed SSL certificate - ios

I operate my own tileserver for maps. This server is accessible via HTTPS with an self signed certificate. Is there a chance to use MKTileOverlay
static NSString * const template = #"https://tile.myserverwithselfsignedcertificate.org/{z}/{x}/{y}.png";
MKTileOverlay *overlay = [[MKTileOverlay alloc] initWithURLTemplate:template];
overlay.canReplaceMapContent = YES;
[self.mapView addOverlay:overlay
level:MKOverlayLevelAboveLabels];
wiht a self-signed-certificate. I receive in the XCode log window unfortunately just an error message that the certificate is invalid.
For direct NSURLConnection requests I can use the solution as decribed e.g. here: http://www.cocoanetics.com/2010/12/nsurlconnection-with-self-signed-certificates/
But this does not work for my customized MKTileOverlay class.
Has anyone an idea if this is possible?
EDIT 21st August 2015
I believe I have to override the MKTileOverlay to something like this:
- (void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *data, NSError *error))result
{
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]
cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20];
connectionApi = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
[myData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
// myData includes now the required tile,
// but how to pass it back to the result
// block of the loadTileAtPath method???
}
Has anyone an idea how too solve this?

I was able to solve it so:
- (void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *data, NSError *error))result
{
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]
cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20];
if (!tileDict)
tileDict = [[NSMutableDictionary alloc] initWithCapacity:100];
NSURLConnection *connectionApi = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
NSURL *myURL = [[connectionApi currentRequest] URL];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
__block id tileNotification;
tileNotification = [center addObserverForName:[NSString stringWithFormat:#"receivedTileFromInternet-%#", myURL]
object:nil
queue:nil
usingBlock:^(NSNotification *notification)
{
NSURL *myURL = [notification.userInfo objectForKey:#"tileUrl"];
if ([tileDict objectForKey:myURL])
{
[[NSNotificationCenter defaultCenter] removeObserver:tileNotification];
NSData *data = [tileDict objectForKey:myURL];
result(data, nil);
}
} ];
}
}
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
NSURL *myURL = [[conn currentRequest] URL];
if (![tileDict objectForKey:myURL])
{
NSMutableData *singleTile = [[NSMutableData alloc] initWithData:data];
[tileDict setObject:singleTile forKey:myURL];
}
else
{
[[tileDict objectForKey:myURL] appendData:data];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
NSURL *myURL = [[conn currentRequest] URL];
if (![tileDict objectForKey:myURL])
{
NSLog(#"Tile leer???");
}
else
{
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:myURL, #"tileUrl", nil];
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:[NSString stringWithFormat:#"receivedTileFromInternet-%#", myURL] object:self userInfo:userInfo];
}
}

Related

Unable to load video stream in

I am new to iOS development,
I want to stream video from webapi, The files are streamed from our backend server which requires authentication. It is key-based authenticated set in the Authorization HTTP Header.
I tried with AVPlayer didn't got my output. After doing some more research, i found customProtocol will be more useful do it so i have used customProtocol and tried with this code but the customProtocol is not getting called customProtocol.h, customProtocol.m
[NSURLProtocol registerClass:[MyCustomProtocol class]];
NSString *theURLString = #"customProtocol://abcd.com/download";
player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:theURLString]];
[self.view addSubview:player.view];
player.view.frame = self.view.frame;
[player play];
Can any one help me here? where i a making mistake?
Thank you in advance!
This is my customProtocol code :
#implementation MyCustomProtocol
+ (BOOL) canInitWithRequest:(NSURLRequest *)request {
NSURL* theURL = request.URL;
NSString* scheme = theURL.scheme;
if([scheme isEqualToString:#"customProtocol"]) {
return YES;
}
return NO;
}
// You could modify the request here, but I'm doing my legwork in startLoading
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
// I'm not doing any custom cache work
+ (BOOL) requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
// This is where I inject my header
// I take the handled request, add a header, and turn it back into http
// Then I fire it off
- (void) startLoading {
NSMutableURLRequest* mutableRequest = [self.request mutableCopy];
Constants *constants = [Constants sharedInstance];
[mutableRequest setValue:[NSString stringWithFormat:#"Bearer %#",constants.access_token] forHTTPHeaderField:#"Authorization"];
NSURL* newUrl = [[NSURL alloc] initWithScheme:#"http" host:[mutableRequest.URL host] path:[mutableRequest.URL path]];
[mutableRequest setURL:newUrl];
self.connection = [NSURLConnection connectionWithRequest:mutableRequest delegate:self];
}
- (void) stopLoading {
[self.connection cancel];
}
// Below are boilerplate delegate implementations
// They are responsible for letting our client (the MPMovePlayerController) what happened
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.client URLProtocol:self didFailWithError:error];
self.connection = nil;
}
- (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:NSURLCacheStorageAllowed];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
[self.client URLProtocolDidFinishLoading:self];
self.connection = nil;
}
if you have passed authentication header with url then you can use below code
NSMutableDictionary * headers = [NSMutableDictionary dictionary];
[headers setObject:#"Your UA" forKey:#"User-Agent"];
AVURLAsset * asset = [AVURLAsset URLAssetWithURL:URL options:#{#"AVURLAssetHTTPHeaderFieldsKey" : headers}];
AVPlayerItem * item = [AVPlayerItem playerItemWithAsset:asset];
self.player = [[AVPlayer alloc] initWithPlayerItem:item];
it may work...try it
MPMoviePlayerViewController * movieController = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
movieController.moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
[self presentMoviePlayerViewControllerAnimated:movieController];
[movieController.moviePlayer play];

How to send data to server and receive response in same methood

Im new to ios i have a doubt that i want to send data to server and receive response in same method
i have a class name
profile.m and i want to send data to service class and receive response in profile class
Profile.m:
NSString *parameter = [NSString stringWithFormat:#"%#&access_token=%#&lksite=social&lkmenu=profile&lktype=view&displayedname=%#&displayid=%#", baseUrl, accessToken, userName,userId];
Service *service = [[Service alloc]init];
[service sendDataToServer:#"POST" andUrl:parameter andUrl:baseUrl];
Service.m
-(void) sendDataToServer:(NSString *) method andUrl:(NSString *) getUrl andUrl:(NSString *)baseUrl{
NSMutableData *jsondata;
Session *ses =[[Session alloc]init];
accessToken = [ses getAccessToken];
NSLog(#"Access Token---> %#",accessToken);
NSString *baseUrl1 = [NSString baseUrl];
if([method isEqualToString:#"GET"]){
NSString *urlStr = [NSString stringWithFormat: #"%#&access_token=%#",getUrl,accessToken];
url = [NSURL URLWithString: urlStr];
urlRequest= [NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPMethod=method;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if( connection )
{
urlMutable = [NSMutableData new];
}
}else{
NSData *parameterData = [getUrl dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
url = [NSURL URLWithString: baseUrl1];
urlRequest=[NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPBody=parameterData;
urlRequest.HTTPMethod=method;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if( connection )
{
urlMutable = [NSMutableData new];
}
}}
You can user NSLocalNotification to achieve your task.
There are three simple steps to use NSLocalNotification.
1) For this you can write your code in Profile.m file as:
- (void)viewDidLoad {
[super viewDidLoad];
Service *Service = [[Service alloc] init];
[Service sendDataToServer:(with your parameters here)];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(responceMethod:) name:#"WebServiceCall" object:nil];
}
2) in your Service.m class make a service call
-(void) sendDataToServer:(NSString *) method andUrl:(NSString *) getUrl andUrl:(NSString *)baseUrl{
NSMutableData *jsondata;
Session *ses =[[Session alloc]init];
accessToken = [ses getAccessToken];
NSLog(#"Access Token---> %#",accessToken);
NSString *baseUrl1 = [NSString baseUrl];
if([method isEqualToString:#"GET"]){
NSString *urlStr = [NSString stringWithFormat: #"%#&access_token=%#",getUrl,accessToken];
url = [NSURL URLWithString: urlStr];
urlRequest= [NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPMethod=method;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if( connection )
{
urlMutable = [NSMutableData new];
}
}else{
NSData *parameterData = [getUrl dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
url = [NSURL URLWithString: baseUrl1];
urlRequest=[NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPBody=parameterData;
urlRequest.HTTPMethod=method;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if( connection )
{
urlMutable = [NSMutableData new];
}
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
int errorCode = (int)httpResponse.statusCode;
NSLog(#"response is %d", errorCode);
[urlMutable setLength: 0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[urlMutable appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Connection failed! Error - %# %#", [error localizedDescription], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *error;
id *response = [NSJSONSerialization JSONObjectWithData:webData options:NSJSONReadingAllowFragments error:&error];
[[NSNotificationCenter defaultCenter] postNotificationName:#"WebServiceCall" object:nil userInfo:response];
}
And finally
3) Implement your response parsing here in the method you have written in Profile.m file like:
-(void)responceMethod:(NSNotification *)notif{
NSDictionary *dict = [notif userInfo];
// Your response parsing.
}
Declare a block as :
typedef void (^completionBlock)(id responseObject , NSError *error);
And then add this block to your methods as :
- (void) performRequestWithCompletion:(completionBlock)block;
On invoking this method, will return you "responseObject" and "error". error nil in case of success

Asynchronous Connection Download Callback

I created a class customDownload with the following methods:
-(NSString *) getTextFromLink: (PreliteRequest *) requestDetails
asyncConnection: (BOOL) isAsync
callbackMethod: (SEL) methodToExecute {
mainRequest = requestDetails;
NSMutableURLRequest *postRequest = [[NSMutableURLRequest alloc] init];
NSURLRequest *getRequest = [[NSURLRequest alloc] init];
NSURLConnection *connection;
NSURLResponse * response = nil;
NSError * error = nil;
if ([[requestDetails getType] isEqualToString:#"POST"]) {
[postRequest setURL:[NSURL URLWithString:[requestDetails getUrl]]];
[postRequest setHTTPMethod:[requestDetails getType]];
[postRequest setValue:[requestDetails getPostLenght] forHTTPHeaderField:#"Content-Length"];
[postRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[postRequest setHTTPBody:[requestDetails getPostParameters]];
if (isAsync) {
tmpMethod = methodToExecute;
connection = [[NSURLConnection alloc] initWithRequest:postRequest delegate:self];
} else
downloadedData = (NSMutableData *)[NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&error];
} else {
getRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#",[requestDetails getUrl],[requestDetails getGetParameters]]]];
if (isAsync) {
tmpMethod = methodToExecute;
connection = [[NSURLConnection alloc] initWithRequest:getRequest delegate:self];
} else
downloadedData = (NSMutableData *)[NSURLConnection sendSynchronousRequest:getRequest returningResponse:&response error:&error];
}
NSString *result=[[NSString alloc]initWithData:downloadedData encoding:NSUTF8StringEncoding];
return result;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
downloadedData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// Append the new data to the instance variable you declared
[downloadedData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSString *tmpResult = [[NSString alloc]initWithData:downloadedData encoding:NSUTF8StringEncoding];
[self performSelector:tmpMethod withObject:tmpResult];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSLog(#"Connection error: %#",error);
}
In my view controller I declare the previous class and call the only method of that class getTextFromLink.
download = [[customDownload alloc] init];
[download getTextFromLink:request asyncConnection:YES callbackMethod:tmpSelector];
SEL tmpSelector = #selector(printResult:);
-(void) printResult:(NSString *) resultToPrint {
NSLog(#"Risultato: %#",resultToPrint);
}
I pass to getTextFromLink the tmpSelector as parameter because that is the method I would like to call as soon the getTextFromDownloadLink has finished its job.
Actually getTextFromLink execute an asynchronous connection.
What I'm trying to do is to execute something when the asyncronous connection finished to download datas.
I would like to create a callback custom class to do this.
Can anyone help me?
Rather than this selector model, generally people would use blocks for this. For example, define a typedef for your block:
typedef void(^PreliteRequestCompletionHandler)(NSString *string);
Since you're dealing with an asynchronous pattern, you might want to define a property which you can use to save this completion handler to call later:
#property (nonatomic, copy) PreliteRequestCompletionHandler completionHandler;
You can then change that selector parameter to be a block parameter:
-(NSString *) getTextFromLink: (PreliteRequest *) requestDetails
asyncConnection: (BOOL) isAsync
completionHandler: (PreliteRequestCompletionHandler)completionHandler {
self.completionHandler = completionHandler;
// do stuff
}
And then, when you want to call that completion block, you do something like:
NSString *result = ...;
if (self.completionHandler) {
self.completionHandler(result);
}
And then you can now use this new block parameter to your method:
download = [[customDownload alloc] init];
[download getTextFromLink:request asyncConnection:YES completionHandler:^(NSString *result) {
NSLog(#"Risultato: %#", result);
}];

iOS NSURLConnection incorrect call

My program register users through URL-requests, but before registration there is existence userlogin or his e-mail checking in remote database. If this data not exist program should add user data in database or (if user or e-mail exist) program should return error.
I wrote this code:
- (IBAction)buttonRegister:(id)sender {
NSString *getDataURL = [NSString stringWithFormat:#"https://*********/********.php?chklogin=%#&chkemail=%#",login.text,email.text];
NSURL *url = [NSURL URLWithString:getDataURL];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection)
urlDataCheckUser = [NSMutableData data];
else NSLog(#"Connection failed!");
}
- (void) msgtitle: (NSString*) title msgtext: (NSString*) msg
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[urlDataCheckUser appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *strResult = [[NSString alloc] initWithData:urlDataCheckUser encoding:NSUTF8StringEncoding];
if ([strResult isEqualToString:#"1"])
{
[self msgtitle:#"Error" msgtext:#"E-mail or Login already use!"];
}
if ([strResult isEqualToString:#""])
{
NSString *getDataURL = [NSString stringWithFormat:#"https://**********/**********.php?reglogin=%#&regemail=%#&regpass=%#",login.text,email.text,password.text];
NSURL *url = [NSURL URLWithString:getDataURL];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url];
NSURLConnection *conn =[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
theRequest = nil;
if (conn)
{
[self msgtitle:#"Success!" msgtext:#"Please login"];
}
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"loginView"];
[self presentViewController:vc animated:YES completion:nil];
}
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
It is work, but i get message about successful registration more then once.
What is wrong?

Show Activity Indicator when fetching JSON data

I am beginner in IOS programming. My question is my app fetching data from JSON in my web server, when starting the apps, it is slightly lag and delay due to the fetching process, so i would like to show activity indicator when i connecting to JSON data. How can i do that?
My JSON coding:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *urlAddress = [NSURL URLWithString:#"http://emercallsys.webege.com/RedBoxApp/getEvents.php"];
NSStringEncoding *encoding = NULL;
NSError *error;
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:urlAddress usedEncoding:encoding error:&error];
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
eventsDetail = [[dict objectForKey:#"eventsDetail"] retain];
}
[jsonreturn release];
}
use the following code
//add a UIActivityIndicatorView to your nib file and add an outlet to it
[indicator startAnimating];
indicator.hidesWhenStopped = YES;
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
//Load the json on another thread
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:urlAddress usedEncoding:encoding error:NULL];
[jsonreturn release];
//When json is loaded stop the indicator
[indicator performSelectorOnMainThread:#selector(stopAnimating) withObject:nil waitUntilDone:YES];
});
You can use something like below code:
- (void)fetchData
{
[activityIndicator startAnimating];
NSURL *url = [NSURL URLWithString:strUrl];
NSURLRequest *theRequest = [[NSURLRequest alloc]initWithURL:url];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if(theConnection) {
}
else {
NSLog(#"The Connection is NULL");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
webData = [[NSMutableData data] retain];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[webData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR with theConenction %#",error);
UIAlertView *connectionAlert = [[UIAlertView alloc] initWithTitle:#"Information !" message:#"Internet / Service Connection Error" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[connectionAlert show];
[connectionAlert release];
[connection release];
[webData release];
return;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
//NSLog(#"Received data :%#",theXML);
//[theXML release];
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary: webData error:&error];
if (dict) {
eventsDetail = [[dict objectForKey:#"eventsDetail"] retain];
}
[activityIndicator stopAnimating];
}

Resources