Segue not working? - ios

I'm building an app around the Feedly API. So, in the UIWebView used to login, I use the following code:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *URLString = [[request URL] absoluteString];
NSString *urlStart = [URLString substringToIndex:23];
if ([urlStart isEqualToString:#"http://localhost/?code="])
{
NSString *haystack = request.URL.absoluteString;
[self useURL:haystack];
}
return YES;
}
As you can see, this calls a method useURL:
- (void)useURL:(NSString *)haystack {
NSString *prefix = #"http://localhost/?code=";
NSString *suffix = #"&state=";suffix!
NSRange needleRange = NSMakeRange(prefix.length,
haystack.length - prefix.length - suffix.length);
NSString *needle = [haystack substringWithRange:needleRange];
NSLog(#"needle: %#", needle);
NSString *valueToSave = needle;
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:#"AuthCode"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSString *client_id = #"id";
NSString *client_secret = #"secret";
NSString *redirect_uri = #"http://localhost";
NSString *state = #"";
NSString *grant_type = #"authorization_code";
NSInteger success = 0;
#try {
NSString *post =[[NSString alloc] initWithFormat:#"code=%#&client_id=%#&client_secret=%#&redirect_uri=%#&state=%#&grant_type=%#",needle,client_id,client_secret,redirect_uri,state,grant_type];
NSLog(#"PostData: %#",post);
NSURL *url=[NSURL URLWithString:#"https://cloud.feedly.com/v3/auth/token"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
//[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Response code: %ld", (long)[response statusCode]);
if ([response statusCode] >= 200 && [response statusCode] < 300)
{
NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Response ==> %#", responseData);
NSError *error = nil;
NSDictionary *jsonData = [NSJSONSerialization
JSONObjectWithData:urlData
options:NSJSONReadingMutableContainers
error:&error];
NSString *accessToken = jsonData[#"access_token"];
NSString *refreshToken = jsonData[#"refresh_token"];
//[self performSegueWithIdentifier:#"presentNewView" sender:self];
NewViewController *newView = [[NewViewController alloc] init];
[self presentViewController:newView animated:NO completion:nil];
} else {
NSLog(#"Failed.");
}
}
#catch (NSException * e) {
NSLog(#"Exception: %#", e);
}
}
Most of it works fine up until the part where the next view should come in. I tried it with a segue and I tried the way as can be seen here, but both keep throwing Exception: *** -[NSURL initFileURLWithPath:]: nil string parameter
What am I doing wrong here?

As your error message states, you have a nil string. You can use breakpoints inside of the class and the LLDB to print the value of said string throughout its lifecycle, using po stringName in the debugger. Find where it looses the value, and you have your answer. Here are some helpful links to help you do this quickly if you're new to LLDB or breakpoints:
Breakpoints Guide
LLDB Commands
If you're more comfortable with using NSLog, placing them in the objects life cycle could be helpful as well, but I would go with the first recommendation.

Related

sendSynchronousRequest:returningResponse deprecated

I have a Xcode app which I am updating to the latest iOS. I now notice that on building I have the following error/warning:
/ConfViewController.m:198:46: 'sendSynchronousRequest:returningResponse:error:' is deprecated: first deprecated in iOS 9.0 - Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h
From what I have read I should start to use "NSURLSession" but how do I use "NSURLSession" in my code, or am I looking at this incorrectly?
My code:
NSString *deviceName = [[UIDevice currentDevice]name];
NSString *post =[[NSString alloc] initWithFormat:#"devicename=%#",deviceName];
NSLog(#"PostData: %#",post);
NSURL *url=[NSURL URLWithString:#"http://www.mydomain/sysscripts/conf/devicelookup17.php"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
//The ERROR point
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//NSLog(#"Response code: %ld", (long)[response statusCode]);
if ([response statusCode] >=200 && [response statusCode] <300)
{
NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Response ==> %#", responseData);
SBJsonParser *jsonParser = [SBJsonParser new];
NSDictionary *jsonData = (NSDictionary *) [jsonParser objectWithString:responseData error:nil];
// NSLog(#"%#",jsonData);
// NSInteger success = [(NSNumber *) [jsonData objectForKey:#"success"] integerValue];
NSInteger roomid = [(NSNumber *) [jsonData objectForKey:#"roomid"] integerValue];
// NSLog(#"%ld",(long)success);
//NSLog(#"%ld",(long)roomid);
NSString *RoomID = [NSString stringWithFormat:#"%ld",(long)roomid];
// NSLog(#"%#", RoomID);
NSString *firstString = #"http://www.mydomain/apps/conf/lon/dt/devices/ /template17.php";
// NSLog(#"%#", firstString);
NSString *roomID = RoomID;
// NSLog(#"%#", roomID);
NSString *newString = [firstString stringByReplacingOccurrencesOfString:#" " withString:roomID];
// NSLog(#"%#", newString);
NSURL *url2 = [NSURL URLWithString: newString];
NSLog(#"%#", url2);
NSURLRequest *request2 = [NSURLRequest requestWithURL:url2];
// ConfViewController *navex =[[ConfViewController alloc] initWithNibName:nil bundle:nil];
//[self presentViewController:navex animated:YES completion:NULL];
[webView loadRequest:request2];
}
Many thanks in advance for your time.
Replace
NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
with
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse * response, NSError * error) {
}] resume];
Put the entire code after the sendSynchronousRequest line in the completion block (between the braces).
Replace
if ([response statusCode] >=200 && [response statusCode] <300)
with
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSInteger statusCode = httpResponse.statusCode;
if (statusCode >= 200 && statusCode < 300)
Replace urlData with data.
Delete
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;

Change from synchronous to Asynchronous

Here i use GET method to fetch data from one Url and display the data in table view.I used synchronous to get data to display.
Needed:
I need to change this code to Asynchronous to display same data in table view.Here i just use my console to display data.
Here my code:
#import "ViewController.h"
#import <CommonCrypto/CommonDigest.h>
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self getdata];
}
-(NSString*)sha256HashFor:(NSString*)input
{
const char* str = [input UTF8String];
unsigned char result[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(str, strlen(str), result);
NSMutableString *ret = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
for(int i = 0; i<CC_SHA256_DIGEST_LENGTH; i++)
{
[ret appendFormat:#"%02x",result[i]];
}
return ret;
}
-(void)getdata {
NSString *userName = #"user#gmail.com";
NSString *password = #"passer";
//encoding
NSData *Data = [password dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [Data base64EncodedStringWithOptions:0];
base64String=[self sha256HashFor: base64String];
NSString *urlString = #"https://api.exampleurl/user23/doc";
NSMutableURLRequest *request= [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"GET"];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", userName, base64String];
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *str = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSLog(#"%#", str);
}
In this code i used base64 and shaa256 encoding.
Can any one help me to do with Asynchronous. I don't know how to do
that. please help me with code explain.
Thanks in advance!
For making Asynchronous http request you can use :
[NSURLConnection sendAsynchronousRequest:httpRequest queue:[AppDelegate connectionQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
....
}];
or you can implement NSURLConnectionDataDelegate protocol
Updated Answer :
First create a connection queue in app delegate file
+ (NSOperationQueue *)connectionQueue
{
dispatch_once(&once, ^{
connectionQueue = [[NSOperationQueue alloc] init];
[connectionQueue setMaxConcurrentOperationCount:2];
[connectionQueue setName:#"com.XYZ.connectionqueue"];
});
return connectionQueue;
}
Here is updated getData Method :
-(void)getdata {
NSString *userName = #"user#gmail.com";
NSString *password = #"passer";
//encoding
NSData *Data = [password dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [Data base64EncodedStringWithOptions:0];
base64String=[self sha256HashFor: base64String];
NSString *urlString = #"https://api.exampleurl/user23/doc";
NSMutableURLRequest *request= [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"GET"];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", userName, base64String];
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
__block NSString *str;
[NSURLConnection sendAsynchronousRequest:httpRequest queue:[AppDelegate connectionQueue]completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
str = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];}];
NSLog(#"%#", str);
}

How to encode a string with special characters that will be POSTed to a URL? Objective-C

Currently I have a string that I want to POST to a URL.
It works perfectly fine except when it encounters special characters like "&", and "?". It will not POST any data that comes after that. For example, if I have a string "I am something & something?", it will only POST "I am something". As for "?", it will be converted to '2' after it has been posted.
reason = 'What see see! Are you sure'2''
I am pretty sure that it must have something to do with encoding as I can see "I am something & something?" as it is just before I set the encoding:
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
I have also tried the encodings below with no success:
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
NSData *postData = [post dataUsingEncoding:NSNonLossyASCIIStringEncoding];
NSData *postData = [post dataUsingEncoding:NSISOLatin1StringEncoding];
Below are my codes from postData onwards:
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
//NSLog(#"PostData: %#", postData);
NSString *check = [[NSString alloc] initWithData:postData encoding:NSASCIIStringEncoding];
NSLog(#"check string = %#", check);
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:strURLQueryString]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSURLResponse *response;
NSError *err=nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSString *strResponse = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"Response: %#", strResponse);
if(err!=nil) {
NSLog(#"Error: %#", [err description]);
}
Please assist.
Your help(s) are appreciated.
There's probably a better answer out there somewhere, but this class extension has been working for me for awhile. I cobbled together the % escapes by looking at a few posts...
// NSString+URLEncoding.h
#interface NSString (NSString_URLEncoding)
- (NSString *)urlEncodeUsingEncoding:(CFStringEncoding)encoding;
- (NSString *)urlEncode;
#end
// NSString+URLEncoding.m
#implementation NSString (NSString_URLEncoding)
- (NSString *)urlEncodeUsingEncoding:(CFStringEncoding)encoding {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(__bridge CFStringRef)self,
NULL,
CFSTR("!*'();:#&=+$,/?%#[]"),
encoding));
}
- (NSString *)urlEncode {
return [self urlEncodeUsingEncoding:kCFStringEncodingUTF8];
}
Then in somer other class to send a string...
// SomeOtherClass.m
#import "NSString+URLEncoding.h"
NSString *encodedString = [#"This & this? are 'challenging' to !% encode" urlEncode];

Issue in json request response, getting blank response

I am stuck with an issue in simple request response in iOS, I am getting blank response in request a url with one post parameter, where the url as it is perfectly working in android and webbrowser
Friends in detail, I have to call
http://example.com/GetCountries
with below http post params
"key"="Abcd1234"
it is working before, but from last few days it is not working, if I check NSError it is showing me The network connection was lost.
and one more thing noticeable here is same server code is on different url and it is working fine, and that url you can test as below
http://example.com/GetCountries
with below http post params
"key"="Abcd1234"
Here is the dropbox link for testing ios source code and also the folder contains Web services test.htm file to test that same url with same post parameter working in browser but not in ios device.
Testing code:
https://dl.dropboxusercontent.com/s/lqrl5b95j2s54mm/Testing.zip?token_hash=AAFgoNfUpQ4FkeswnPdGiMVzdMtSM6js9KySJm_OH6lZXQ&dl=1
thank you
So I could not get the form per se to work but was able to recraft it to work. Note a few things:
you should convert to ARC!
you need a strong reference to the connection so you can release it later on (and not in a delegate method!)
you need the delegate connectionSucceeded method (to record response whatever!)
CODE:
- (void)asynchronousRequest
{
[activity startAnimating];
NSString *requesturl = lblURL.text;
NSLog(#"requesturl=%#", requesturl);
NSURL *theURL = [NSURL URLWithString:requesturl];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"content-type"];
[request setURL:theURL];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setTimeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
NSString *str = [NSString stringWithFormat:#"key=%#", [self URLencodedString:#"Abcd1234"]];
NSLog(#"BODY: %#", str);
NSData *body = [str dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"URL : %#", requesturl);
NSLog(#"REQ : %#", request);
[request setHTTPBody:body];
[request addValue:[NSString stringWithFormat:#"%u", [body length]] forHTTPHeaderField:#"Content-Length"];
NSLog(#"AllFields : %#", [request allHTTPHeaderFields]);
NSLog(#"HTTPBody : %#", [[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding]);
NSLog(#"HTTPMethod : %#", [request HTTPMethod]);
self.activeDownload = [NSMutableData data];
conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
assert(conn);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
assert([response isKindOfClass:[NSHTTPURLResponse class]]);
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(#"GOT %d", [httpResponse statusCode]);
}
- (NSString *)URLencodedString:(NSString *)s
{
CFStringRef str = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)s, NULL, (CFStringRef)#"!*'();:#&;=+$,/?%#[]", kCFStringEncodingUTF8);
NSString *newString = [(NSString *)str stringByReplacingOccurrencesOfString:#" " withString:#"+"];
if(str) CFRelease(str);
return newString;
}
EDIT: Modified Code that still didn't work:
- (void)asynchronousRequest
{
[activity startAnimating];
NSString *boundary = #"1010101010"; // DFH no need for the leading '--'
NSString *contentType = [NSString stringWithFormat:#"multipart/form-data; boundary=%#",boundary];
NSMutableDictionary *postVariables = [[NSMutableDictionary alloc] init];
[postVariables setValue:#"Abcd1234" forKey:#"key"];
NSString *requesturl = lblURL.text;
NSMutableString *myStr = [[NSMutableString alloc] init];
NSString *str;
// DFH - strategy is to have each line append its own terminating newline/return
str = [NSString stringWithFormat:#"--%#\r\n",boundary]; // DFH initial boundary
[myStr appendString:str];
NSArray *formKeys = [postVariables allKeys];
for (int i = 0; i < [formKeys count]; i++) {
str = [NSString stringWithFormat:#"Content-Disposition: form-data; name=\"%#\"\r\n%#\r\n",[formKeys objectAtIndex:i],[postVariables valueForKey:[formKeys objectAtIndex:i]]];
[myStr appendString:str];
str = [NSString stringWithFormat:#"--%#\r\n",boundary]; // DFH mid or terminating boundary
[myStr appendString:str];
}
NSLog(#"BODY: %#", myStr);
NSData *body = [myStr dataUsingEncoding:NSUTF8StringEncoding];
requesturl = [self encodeStringForURL:requesturl];
NSLog(#"requesturl=%#", requesturl);
NSURL *theURL = [NSURL URLWithString:requesturl];
self.activeDownload = [NSMutableData data];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:theURL];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setTimeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
[request setValue:contentType forHTTPHeaderField: #"Content-Type"]; // DFH you add addValue, I always use setValue
NSLog(#"URL : %#", requesturl);
NSLog(#"REQ : %#", request);
NSLog(#"ContentType \"%#\"", contentType);
if(body)
{
[request setHTTPBody:body];
}
NSLog(#"AllFields : %#", [request allHTTPHeaderFields]);
NSLog(#"HTTPBody : %#", [[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding]);
NSLog(#"HTTPMethod : %#", [request HTTPMethod]);
conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
assert(conn);
}
I have used ASIHTTP Library and my problem is solved

About ASIHTTPRequest send request

I'm using ASIHTTPRequest [request startAsynchronous] functon to send a request to my webservice api to login. If the request is ok, it returns a json value. Then I send another request to get user's info, but here I receive an error.
Here is my code:
-(void)login
{
[usernameTextField resignFirstResponder];
[passwordTextField resignFirstResponder];
username = [usernameTextField text];
password = [passwordTextField text];
if ( ([username length] == 0 ) || ([password length] == 0 ))
{
...
}
else
{
NSString *URL = [NSString stringWithFormat:#"https://xxx.xxx.xx.xx/FMS/Pages/Service/FMService.svc/Login?user=%#&pass=%#",username,password];
NSURL *requestURL = [NSURL URLWithString:URL];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:requestURL];
[request setValidatesSecureCertificate:NO];
[request setDelegate:self];
[request startAsynchronous];
}
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSError *error = [request error];
if (!error)
{
NSString *responseString = [request responseString];
NSDictionary *responseDict = [responseString JSONValue];
NSString *unlockCode = [responseDict objectForKey:#"d"];
if ( [unlockCode isEqualToString:#"successful"] )
{
NSURL *url = [NSString stringWithFormat:#"https://xxx.xxx.xx.xx/FMS/Pages/Service/FMService.svc/GetUserInfo?user=%#",username];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setValidatesSecureCertificate:NO];
[request startSynchronous];**//THERE IS AN ERROR**
NSError *error = [request error];
if (!error)
{
NSDictionary *responseDict = [responseString JSONValue];
NSString *realName = [responseDict objectForKey:#"RealName"];
NSLog(#"%#",realName);
}
}
else
{
//...
}
}
else
{
NSLog(#"%#",[error description]);
}
}
And there is an error:
[__NSCFString absoluteURL]: unrecognized selector sent to instance
0x69ef4b0
Another error:
void SendDelegateMessage(NSInvocation*): delegate
(_selectionLayoutChangedByScrolling:) failed to return after waiting
10 seconds. main run loop mode: kCFRunLoopDefaultMode
This line is incorrect:
NSURL *url = [NSString stringWithFormat:#"https://xxx.xxx.xx.xx/FMS/Pages/Service/FMService.svc/GetUserInfo?user=%#",username];
It should be changed to:
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://xxx.xxx.xx.xx/FMS/Pages/Service/FMService.svc/GetUserInfo?user=%#",username]];

Resources