Suppose i have two classes A & B. class A calls the asynchronus method Foo in class B. Foo method fetches data using asynchronous ASIHTTPRequest and send the data from Foo back as the return value to Class A. Class A will use that returned data and do the things
I am creating a object of my class URLParser here in another class and calling the function getJsonUrl , it will parse and get the json url for me . I am using that returned URL in another ASIHTTPRequest here . But i am getting EXC_BAD_ACCESS ...help me to figure it out ....
......
URLParser *urlParser = [[URLParser alloc] init];
NSString *JsonString = [urlParser getJsonUrl:#"http://mywebs.com/?q=iphone/news"];
NSLog(#" url returned = %#" ,JsonString);
NSURL *JsonUrl = [NSURL URLWithString:JsonString];
newsRequest = [ASIHTTPRequest requestWithURL:JsonUrl];
[newsRequest setDelegate:self];
[newsRequest startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
newsDictionary = [[NSMutableDictionary alloc] init];
NSData *responseData = [request responseData];
NSString *response = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding] ;
self.newsDictionary = [response JSONValue];
[response release];
[self getDataNews:self.newsDictionary];
}
URL Parser Class
#synthesize albumDic;
#synthesize GlobalRequest;
-(NSString*)getJsonUrl:(NSString *)url{
GlobalRequest = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
[GlobalRequest setDelegate:self];
[GlobalRequest startAsynchronous]; // when i called the [GlobalRequest startSynchronous] ....both cases m getting the same error
return JsonStr;
}
- (void)requestFinished:(ASIHTTPRequest *)request{
albumDic = [[NSMutableDictionary alloc] init];
NSData *responseData = [request responseData];
NSString *response = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding] ;
self.albumDic = [response JSONValue];
[response release];
[self GetDictionary:self.albumDic];
}
- (void)requestFailed:(ASIHTTPRequest *)request{
[request cancel];
}
Related
I have a class where I request information from a provider class, in which after finalizing the job (asynchronous httpRequest block) needs to invoke a method [- (void) updateCountries] in the requester class. If I am not wrong this code worked in iOS 7, but now in iOS 8 it does not.
Can you please help me to understand why?
Methods in requester class:
- (void) viewWillAppear:(BOOL)animated {
//get countries to pickerView
webAPI = [[WebAPI alloc] init];
[webAPI retrieveCountries:self];
}
- (void) updateCountries {
//update countries content for pickerView
locationDAO = [[LocationDAO alloc] init];
countriesArray = [locationDAO getCountries];
[pickerView reloadAllComponents];
}
Lines in method in provider class where error happens:
SEL updateCountries = sel_registerName("updateCountries:");
[requester performSelectorOnMainThread:updateCountries withObject:nil waitUntilDone:YES];
If you need to checkout the entire method in the provider class, here it is:
- (void) retrieveCountries:(id)requester {
// NSLog(#"engine report: firing retrieveCountries http get");
NSString *urlAsString = kRetrieveCountriesListAPI;
NSURL *url = [NSURL URLWithString:urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:#"GET"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ([data length] >0 && error == nil){
NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"engine report: retrieveCountries server response: %#", response);
NSArray *level0 = [[NSArray alloc] initWithObjects:[NSJSONSerialization JSONObjectWithData:[[NSData alloc] initWithData:data] options:kNilOptions error:&error], nil];
NSArray *level1 = [level0 objectAtIndex:0];
LocationDAO *locationDAO = [[LocationDAO alloc] init];
[locationDAO deleteAllFromCountries];
for (int i = 0; i < [level1 count]; i++) {
CountryVO *countryVO = [[CountryVO alloc] init];
countryVO.myID = [[[level1 objectAtIndex:i] objectForKey:#"id"] integerValue];
countryVO.name = [[level1 objectAtIndex:i] objectForKey:#"country_name"];
[locationDAO saveCountryToDatabase:countryVO];
}
SEL updateCountries = sel_registerName("updateCountries:");
[requester performSelectorOnMainThread:updateCountries withObject:nil waitUntilDone:YES];
dispatch_async(dispatch_get_main_queue(), ^(void){
});
} else if ([data length] == 0 && error == nil){
NSLog(#"Nothing was downloaded.");
} else if (error != nil) {
NSLog(#"Error happened = %#", error);
} }];
}
THANK YOU A WHOLE LOT
Remove the : from the selector specification:
SEL updateCountries = sel_registerName("updateCountries");
Your method updateCountries doesn't take any arguments. So, when creating the selector, you should only write updateCountries (instead of updateCountries: which would indicate that this method takes an argument).
The reason why your app crashes is that when you try to perform this selector, the internals of your app are looking for a method called updateCountries on requester that takes one argument. This method doesn't exist, which is why the app crashes.
I am working with an application where I have to request a url and I get the response accordingly
I am using ASIHTTPRequest to request the URL
here is my request
-(void)getTips {
if ([CommonFunctions networkConnected]) {
ShowNetworkActivityIndicator();
NSString *strPhp = #"staticpage.php";
NSString *strQuery = [[NSString alloc] initWithString:[NSString stringWithFormat:#"%#%#?static_id=3",GMS_URL,strPhp]];
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:strQuery]];
NSLog(#"tips url %#",request.url);
request.delegate = self;
[request setRequestMethod:#"GET"];
[request startAsynchronous];
}
}
These are my delegate methods
-(void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data {
// NSString *responseStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// NSLog(#"responseStr %#",responseStr);
SBJsonParser *json = [[SBJsonParser alloc]init];
NSLog(#"json data %#",[json objectWithData:data]);
NSMutableArray *marrData = [[json objectWithData:data] valueForKey:#"responseData"];
if([[marrData valueForKey:#"result"] isEqualToString:#"failed"]){
[CommonFunctions showAlertMessage:[marrData valueForKey:#"error"]];
}
HideNetworkActivityIndicator();
}
Here I get null data no matter whether I pass request methods GET or POST
When I check the same url in browser I get the response and a valid json from online json viewer
What are the possible reason that I am getting null data in the application
Use requestFinished: delegate.. Please try this.
-(void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"response %#", [request responseString]);
}
I am trying to use one of iOS7 new features, the JavaScriptCore Framework. I can successfully output a helloWorld string from Javascript, but what I'm interested in, is doing HTTP POSTs in Javascript and then pass the response to Objective-C. Unfortunately, when I'm creating an XMLHttpRequest object in Javascript, I get EXC_BAD_ACCESS (code=1, address=....).
Here is the Javascript code (hello.js):
var sendSamplePost = function () {
// when the following line is commented, everything works,
// if not, I get EXC_BAD_ACCESS (code=1, address=....)
var xmlHttp = new XMLHttpRequest();
};
var sayHello = function (name) {
return "Hello " + name + " from Javascript";
};
Here is the Objective-C code inside my ViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
JSContext *context = [[JSContext alloc] initWithVirtualMachine:[[JSVirtualMachine alloc] init]];
NSString *scriptPath = [[NSBundle mainBundle] pathForResource:#"hello" ofType:#"js"];
NSLog(#"scriptPath: %#", scriptPath);
NSString *script = [NSString stringWithContentsOfFile:scriptPath encoding:NSUTF8StringEncoding error:nil];
NSLog(#"script: %#", script);
[context evaluateScript:script];
JSValue *sayHelloFunction = context[#"sayHello"];
JSValue *returnedValue = [sayHelloFunction callWithArguments:#[#"iOS"]];
// this works!
self.label.text = [returnedValue toString];
JSValue *sendSamplePostFunction = context[#"sendSamplePost"];
// this doesn't work :(
[sendSamplePostFunction callWithArguments:#[]];
}
Could it be that HTTP Requests functionality is not provided in JavaScriptCore Framework? If yes, could I overcome this by using UIWebView's -stringByEvaluatingJavaScriptFromString:? What if I compiled and included in my project another Javascript Engine (e.g. V8)?
XMLHttpRequest is, as stated before, not part of JavaScript, but you still can wrap the iOS URLRequest so it's available in your JS.
in JSUtils.h
#protocol UtilsExport;
#interface JSUtils : NSObject <UtilsExport>
#end
#protocol UtilsExport <JSExport>
- (void)get:(NSString *)url then:(JSValue *)jsCallback;
#end
in JSUtils.m
#import "JSUtils.h"
- (void)get:(NSString *)url then:(JSValue *)callback {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:10];
[request setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ([data length] > 0 && error == nil) {
[callback callWithArguments:#[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding], #YES]];
}
}];
}
Next, bind the instance to the JSContext somewhere in your code
JSContext *context = [[JSContext alloc] init];
context[#"utils"] = [[JSUtils alloc] init];
from your JS file, you can now call
utils.getThen('http://localhost/api/dashboard', function(resultString){
console.log(resultString)
}
You could also use a block and bind it straight to the JSContext to get the same result.
My guess would be that HTTP Requests are not part of JavaScript Core, as it's really part of the browser, not the JavaScript Language.
I would assume that JavaScript core only includes what's in the ECMAScript definition.
If you want AJAX, then the WebView is the way to go.
JSContext *context = [[JSContext alloc] init];
context[#"request"] = ^(NSString *url) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:10];
NSURLResponse *response = nil;
[request setHTTPMethod:#"GET"];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return body;
};
In JS:
var body = request(url);
I have a project I am working on that has a number of different news feeds and announcement boards that displays post from various sources. Currently I have the code for the like, delete and flag buttons in methods contained in each class file for the views that display the feeds. I have been trying to craft a utility class that allows me to place the code for the three functionalities listed above in one object to be used throughout the project. I have done the exact same type of thing in C++ or Java, but am having issues reproducing it in objective-c. The like, delete and flag buttons use the NSURL libraries to interact with the web service. Bellow is an example of one of the methods I am trying to implement in the utility class, and is the code used to be implemented in the like buttons:
+ (void)btnLikeAction:(UIButton *)btnLike userIdString:(NSString *)userId contentSource:(NSString *)sourceId cellUsed:(NewsfeedCell *)cell dataForCell:(Post *)post
{
BOOL hasLiked = post.hasLiked;
UILabel *likeLabel = cell.likeCount;
NSString *pId = post.postId;
if (hasLiked)
{
[btnLike setEnabled:NO];
NSString *url = [NSString stringWithFormat: #"http://192.155.94.183/api/v1/likes/unlike/%#/%#/%#/", sourceId, pId, userId];
NSURL *URL = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
int localCount = [likeLabel.text intValue];
localCount--;
likeLabel.text = [NSString stringWithFormat:#"%i", localCount];
post.likeCount = [NSString stringWithFormat:#"%i", localCount];
post.hasLiked = NO;
[btnLike setEnabled:YES];
}
else
{
[btnLike setEnabled:NO];
NSError *err = nil;
NSDictionary *likeData = [NSDictionary dictionaryWithObjectsAndKeys:
userId, #"user_id",
pId, #"source_id",
sourceId, #"source",
nil];
NSData *JSONLike = [NSJSONSerialization dataWithJSONObject:likeData options:NSJSONWritingPrettyPrinted error:&err];
NSString *url = #"http://192.155.94.183/api/v1/likes.json";
NSURL *URL = [NSURL URLWithString:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [JSONLike length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:JSONLike];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
int localCount = [likeLabel.text intValue];
localCount++;
likeLabel.text = [NSString stringWithFormat:#"%i", localCount];
post.likeCount = [NSString stringWithFormat:#"%i", localCount];
post.hasLiked = YES;
[btnLike setEnabled:YES];
}
}
This code uses a web service to update the number of likes for a specific piece of content. It works when the method is placed into the individual ViewController class files, but when I try to make a utility class with the individual methods I run into issues with the didReceiveAuthenticationChallenge, didReceiveResponse, didReceiveData and connectionDidFinishLoading methods not being called. Originally, I assumed that the delegate methods would be called in the file that that the utility methods were called in. But that was not the case. When I implemented the method definitions in the actual utility class, the methods still weren't called. I did some research on the topic and looked into this article but found I was unable to find substantial resources that helped my specific situation. How do I set up my utility class? I can post the full code of the utility if needed.
As #serrrgi already said, the problem is that btnLikeAction:... is a class method, so that self is the class itself. You have the following options:
Make all delegate methods class methods, e.g.
+ (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"didReceiveResponse");
}
Create an instance of your Utility class and use that as delegate:
YourClass *u = [[self alloc] init];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:u];
Use sendAsynchronousRequest:..., which does not need a delegate:
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data != nil) {
NSLog(#"success");
} else {
NSLog(#"error: %#", error);
}
}];
I use the following code to create a dictionary based on a JSON string received from the server. (I have downloaded JSONKit and embedded it into the project). The code below returns a legal JSON string from the server (parsed well on Android) but crashes when I try to convert it to a dictionary.
- (IBAction)submit
{
bool useSSL = true;
char *c_url="http://(rest of URL)";
NSString* url = [NSString stringWithFormat:#"%s" , c_url];
url = [NSString stringWithFormat:#"%#%#%s", url, self.label.text, "/keys"];
NSString * response = [self getDataFrom:url];
NSDictionary *dict = [response objectFromJSONString]; //generates SIGABRT!!
NSLog(#"%#",dict);
NSString *success = [dict valueForKey:#"success"];
}
- (NSString *) getDataFrom:(NSString *)url{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"GET"];
[request setURL:[NSURL URLWithString:url]];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *responseCode = nil;
NSData *oResponseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&responseCode error:&error];
if([responseCode statusCode] != 200){
NSLog(#"Error getting %#, HTTP status code %i", url, [responseCode statusCode]);
return nil;
}
return [[NSString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding];
}
THANKS,
Simon
Found an answer here.
Answer says: "Figured it out... I had JSONKIt.h included in the project but for some weird reason, JSONKit.m was not included in the 'Compile Sources' under 'Build Phases' - once I added it manually it started working fine."