iPhone JSON Object - iphone

I'm trying to create a application that will retrieve JSON data from an HTTP request, send it to a the application main controller as a JSON object then from there do further processing with it.
Where I'm stick is actually creating a class that will serve as a JSON class in which will take a URL, grab the data, and return that object.
Alone, im able to make this class work, however I can not get the class to store the object for my main controller to retrieve it.
Because im fairly new to Objective-C itself, my thoughts are that im messing up within my init call:
-initWithURL:(NSString *) value
{
responseData = [[NSMutableData data] retain];
NSURL *theURL = [NSURL URLWithString:value];
NSURLRequest *request = [NSURLRequest requestWithURL:theURL];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
return self;
}
The processing of the JSON object takes place here:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSError *jsonError;
SBJSON *json = [[SBJSON new] autorelease];
NSDictionary *parsedJSON = [json objectWithString:responseString error:&jsonError];
// NSArray object.
listings = [parsedJSON objectForKey:#"posts"];
NSEnumerator *enumerator = [listings objectEnumerator];
NSDictionary* item;
// to prove that it does work.
while (item = (NSDictionary*)[enumerator nextObject]) {
NSLog(#"posts:id = %#", [item objectForKey:#"id"]);
NSLog(#"posts:address = %#", [item objectForKey:#"address"]);
NSLog(#"posts:lat = %#", [item objectForKey:#"lat"]);
NSLog(#"posts:lng = %#", [item objectForKey:#"lng"]);
}
[responseString release];
}
Now when calling the object within the main controller I have this bit of code in the viewDidLoad method call:
- (void)viewDidLoad {
[super viewDidLoad];
JSON_model *jsonObj = [[JSON_model alloc] initWithURL:#"http://localhost/json/faith_json.php?user=1&format=json"];
NSEnumerator *enumerator = [[jsonObj listings] objectEnumerator];
NSDictionary* item;
//
while (item = (NSDictionary*)[enumerator nextObject]) {
NSLog(#"posts:id = %#", [item objectForKey:#"id"]);
NSLog(#"posts:address = %#", [item objectForKey:#"address"]);
NSLog(#"posts:lat = %#", [item objectForKey:#"lat"]);
NSLog(#"posts:lng = %#", [item objectForKey:#"lng"]);
}
}

take a look at TouchJSON project - http://code.google.com/p/touchcode/wiki/TouchJSON

I think things are happening in the wrong order.
enter viewDidLoad
[JSON_Model initWithURL] is called from viewDidLoad
initWithURL starts fetching data asynchronously.
initWithURL finishes and returns to viewDidLoad.
viewDidLoad continues and displays the empty content of listings
... Time passes whilst the server generates the JSON and returns it.
connectionDidFinishLoading is called once the iPhone recieves the data
connectionDidFinishLoading populates listings with the JSON data.
listings is not access again
the view is never told to refresh once the JSON data has been loaded and parsed.

I found this website to be helpful for using a JSON object in my app.

Related

Parse json with NSJSONSerialization class using objectForKey in iOS

I am new in iOS development. I use this code to connect to my REST Web Service and fetch data in Json format.
NSString *url=#"URL_Address";
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLResponse *resp = nil;
NSError *err = nil;
NSData *response = [NSURLConnection sendSynchronousRequest: theRequest returningResponse: &resp error: &err];
// NSString * theString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
// NSLog(#"response: %#", theString);
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: response options: NSJSONReadingMutableContainers error: &err];
if (!jsonArray) {
NSLog(#"Error parsing JSON: %#", err);
} else {
for(NSDictionary *item in jsonArray) {
NSLog(#" %#", item);
NSLog(#"---------------------------------");
}
}
Now I want to seperate them via objectForKey. I used this code inside the loop :
NSString *name = [item objectForKey:#"name"];
It does not work. I got this error:
2012-07-31 12:48:38.426 LearningAFNetworking[390:f803] -[__NSArrayM objectForKey:]: unrecognized selector sent to instance 0x6844460
2012-07-31 12:48:38.428 LearningAFNetworking[390:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM objectForKey:]: unrecognized selector sent to instance 0x6844460'
*** First throw call stack:
(0x13c8022 0x1559cd6 0x13c9cbd 0x132eed0 0x132ecb2 0x2f40 0x2bf8 0xd9a1e 0x38401 0x38670 0x38836 0x3f72a 0x290b 0x10386 0x11274 0x20183 0x20c38 0x14634 0x12b2ef5 0x139c195 0x1300ff2 0x12ff8da 0x12fed84 0x12fec9b 0x10c65 0x12626 0x254d 0x24b5 0x1)
terminate called throwing an exception(lldb)
can you help me?
You have to access the 0 item of item array:
NSArray *mainArray = [item objectAtIndex:0];
(NSDictionary *obj in mainArray) {
NSString *name = [obj objectForKey:#"name"];
}
When you got this error: -[__NSArrayM objectForKey:], you need to realize that the object that you're trying to access isn't a dictionary. It's an array (__NSArrayM), so you have to first access the 0 index, and then starting exploring the dictionary.
Take a look at this amazing tutorial, from Ray Wenderlich, that explains everything about crashes.
As Alberto said, you assumed that item is an NSDictionary while in reality is an NSArray containing multiple dictionaries. Now for the drill-down part you can use valueForKeyPath as shown below. So your for loop should be something like this:
NSArray *items = [jsonArray objectAtIndex:0];
for (NSDictionary *item in items){
NSString *name = [item valueForKey:#"name"];
// You can also get nested properties like this
NSString *projectName = [item valueForKeyPath:#"project.name"];
}
Another useful thing to know is that if you'd like to get all 'name' values for example, you could use valueForKey on your items array, which would automatically call valueForKey on each dictionary for you. Example:
NSArray *items = [jsonArray objectAtIndex:0];
NSArray *names = [items valueForkey:#"name"];
From the error and from the log output of your code it looks like your are trying to execute the selector objectForKeyon a NSArray.
Try to change NSString *name = [item objectForKey:#"name"];to NSString *name = [[item objectAtIndex: 0]objectForKey:#"name"];
May this code help you to get the first object of type dictionary from the NSArray
[[jsonArray objectAtIndex:0]objectForKey:#"object-key"];
-(void)clientServerCommunication
{
NSURL *url = [NSURL URLWithString:#"http://182.72.122.106/iphonetest/getTheData.php"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:req delegate:self];
if (connection)
{
webData = [[NSMutableData alloc]init];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
/*Third party API
NSString *respStr = [[NSString alloc]initWithData:webData encoding:NSUTF8StringEncoding];
SBJsonParser *objSBJson = [[SBJsonParser alloc]init];
NSDictionary *responseDict = [objSBJson objectWithString:respStr]; */
resultArray = [[NSArray alloc]initWithArray:[responseDict valueForKey:#"result"]];
NSLog(#"resultArray: %#",resultArray);
[self.tableView reloadData];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
custcell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(custcell==nil)
{
custcell=[[[NSBundle mainBundle]loadNibNamed:#"custumCell" owner:self options:nil]objectAtIndex:0];
}
custcell.persnName.text=[[arr objectAtIndex:indexPath.row]valueForKey:#"Name"];
//else if (objsegment.selectedSegmentIndex==1)
//{
custcell.persnAge.text=[[arr objectAtIndex:indexPath.row]valueForKey:#"Age"];
[sortcontrol addTarget:self action:#selector(SegmentbtnCLK:) forControlEvents:UIControlEventValueChanged];
//objsegment.selectedSegmentIndex=0;
// }
return custcell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here, for example:
//Create the next view controller.
detailViewController *detailViewController1 = [[detailViewController alloc]initWithNibName:#"detailViewController" bundle:nil];
//detailViewController *detailViewController = [[detailViewController alloc] initWithNibName:#"detailViewController" bundle:nil];
// Pass the selected object to the new view controller.
// Push the view controller.
detailViewController1.nextDict = [[NSDictionary alloc]initWithDictionary:[resultArray objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:detailViewController1 animated:YES];
// Pass the selected object to the new view controller.
// Push the view controller.
// [self.navigationController pushViewController:detailViewController animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
empName.text=[nextDict valueForKey:#"name"];
deptlbl.text=[nextDict valueForKey:#"department"];
designationLbl.text=[nextDict valueForKey:#"designation"];
idLbl.text=[nextDict valueForKey:#"id"];
salaryLbl.text=[nextDict valueForKey:#"salary"];
NSString *ImageURL = [nextDict valueForKey:#"image"];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
image.image = [UIImage imageWithData:imageData];
}

retrieve all data of nsarray

I'm using JSON parsing to get data from MySql by using php
I got all data I want, But when I want to print this data I created a for loop but It gives me the last element only .. this is my code
in DidViewLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *phpUrl = #"http://dt-works.com/eman/bookOwn.php";
NSString *dbName = #"dbName";
NSString *localHost = #"localhost";
NSString *dbUser = #"dbUser";
NSString *dbPwd = #"dbPwd";
int u_id = 1;
NSString *user_id = [NSString stringWithFormat:#"%d",u_id];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:phpUrl]];
[request setHTTPMethod:#"POST"];
NSString *post = [[NSString alloc] initWithFormat:#"dbName=%#&localHost=%#&dbUser=%#&dbPwd=%#&user_id=%#&submit=", dbName, localHost, dbUser, dbPwd, user_id];
[request setHTTPBody:[post dataUsingEncoding:NSUTF8StringEncoding]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSArray *statuses = [parser objectWithString:json_string error:nil];
int arraySize = [statuses count];
for (NSDictionary *status in statuses)
{
bo_id2 = [status objectForKey:#"bo_id"];
bo_name2 = [status objectForKey:#"bo_name"];
bo_au_id2 = [status objectForKey:#"bo_au_id"];
bo_pub_id2 = [status objectForKey:#"bo_pub_id"];
bo_num_pages2 = [status objectForKey:#"bo_num_pages"];
bo_publish_year2 = [status objectForKey:#"bo_publish_year"];
}
NSLog(#"size of array is: %d", arraySize);
for (int i=0; i<arraySize; i++) {
NSLog(#"%d:",i);
// here I want to retrieve all array elements .. when I try
NSLog(#"Book id: %# - book name: %#", bookId, bookName);
// this give me the last elemet only not all data
// I want to get the data here to use it later .. how ???
}
}
any help ??
You appear to just be reassigning the values of each object to an instance variable, an instance variable only points to one object, not all the ones you assign it to.
Most probably you must have been reintializing the array some where. Check that in the entire code.
NSLog(#"Book id: %# - book name: %#", bookId, bookName);
How do you get the bookId and bookName values in the NSLog above? Something missing in your code there.
You can try this :
for(NSDictionary *status in statuses) {
NSLog(#"Book id: %# - Book Name: %#", [status objectForKey:#"bo_id"], [status objectForKey: #"bo_name"]);
}
In other terms, if you want to use a second for loop, go the same way as the first one.
I don't quite understand why you have to use two for loop to finish the task, in your first loop
NSMutableArray *books = [[NSMutableArray alloc] init];
for(NSDictionary *status in statuses){
[books addObject:status];
}
Later when you want to retrieve any books, you can just call [books objectAtIndex:index].
Hopefully this can help.
You should be able to finish all the tasks you asked for.
Edit
If you just want just one element, bo_name for example you can use:
NSMutableArray *books =[[NSMutableArray alloc] init];
for(NSDictionary *status in statuses){
[books addObject:[status objectForKey:#"bo_name"]];
}

Can we retrieve a particular method from json file and display it on UI ?

Hi everyone, I am new to iphone development..I am doing some application where I am stuck...I am having a textfield, button and a webview..
I am having a parsed json file..
I want to enter a string or method in the textfield, which is present in the JSON file..It should match with the method in json file and should display the contents of a method on webview..
I have done with button and a webview... I want to extend further with textfield and webview..
How can we do it? Please suggest me with example code...
//code
- (void)loadData
{
dataWebService = [[NSMutableData data] retain];
NSURLRequest *request = [[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://api.kivaws.org/v1/loans/search.json?status=fundraising"]]retain];
[[NSURLConnection alloc]initWithRequest:request delegate:self];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:dataWebService encoding:NSUTF8StringEncoding];
self.dataWebService = nil;
NSArray* latestLoans = [(NSDictionary*) [responseString JSONValue] objectForKey:#"loans"];
[responseString release];
NSDictionary* loan = [latestLoans objectAtIndex:0];
//fetch the data
NSNumber* fundedAmount = [loan objectForKey:#"funded_amount"];
NSNumber* loanAmount = [loan objectForKey:#"loan_amount"];
float outstandingAmount = [loanAmount floatValue] - [fundedAmount floatValue];
NSString* name = [loan objectForKey:#"name"];
NSString* country = [(NSDictionary*)[loan objectForKey:#"location"] objectForKey:#"country"];
//set the text to the label
label.numberOfLines = 0;
label.text = [NSString stringWithFormat:#"Latest loan: %# \n \n country: %# \n \n amount: $%.2f", name,country,outstandingAmount];
}
I think you are asking this: "How can I enter part of the URL in a textfield, and have it appended to a base URL and loaded into the webview?"
If so, you can do it quite easily. If your textfield is called "textfield" and webview called "webview" then do this:
NSString *baseUrl = #"http://whatever.com";
NSString *fullUrl = [baseUrl stringByAppendingString:textfield.text];
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:fullUrl]]];
Trigger it either with a button press or with UITextFieldDelegate's - (BOOL)textFieldShouldReturn:(UITextField *)textField
Edit:
You want to retrieve a value from the NSDictionary that the JSON generated based on a key you specify in the textfield. First, do
NSString *value = [dictionary objectForKey:textfield.text];
to get the value (assuming it is a string here). Then you want to display the value in a webview. You can either do it with loadHTMLString:baseURL: or with javascript via stringByEvaluatingJavaScriptFromString: (both methods of UIWebView). If you want to use loadHTMLString for example you can put in
NSString *html = [NSString stringWithFormat:#"<html><body>%#</body></html>", value];
[webview loadHTMLString:html baseURL:nil];

NSOperation and EXC_BAD_ACCESS

I have a few apps which are largely data driven, so most screens are basically composed of:
Open the screen
Download the data via an NSOperation
Display data in a UITableView
Make a selection from the UITableView
Go to new screen, and start over from step 1
I am finding that everything works in normal usage, but if the user goes away from the app for a while and then comes back, I'm getting an EXC_BAD_ACCESS error when the next NSOperation runs. This doesn't seem to matter if the user sends the app into the background or not, and it only seems to occur if there's been at least a few mins since the previous data connection was made.
I realise this must be some form of over-releasing, but I'm pretty good with my memory management and I can't see anything wrong. My data calls generally look like this:
-(void)viewDidLoad {
[super viewDidLoad];
NSOperationQueue* tmpQueue = [[NSOperationQueue alloc] init];
self.queue = tmpQueue;
[tmpQueue release];
}
-(void)loadHistory {
GetHistoryOperation* operation = [[GetHistoryOperation alloc] init];
[operation addObserver:self forKeyPath:#"isFinished" options:0 context:NULL];
[self.queue addOperation:operation];
[operation release];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqual:#"isFinished"] && [object isKindOfClass:[GetHistoryOperation class]]) {
GetHistoryOperation* operation = (GetHistoryOperation*)object;
if(operation.success) {
[self performSelectorOnMainThread:#selector(loadHistorySuceeded:) withObject:operation waitUntilDone:YES];
} else {
[self performSelectorOnMainThread:#selector(loadHistoryFailed:) withObject:operation waitUntilDone:YES];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
-(void)loadHistorySuceeded:(GetHistoryOperation*)operation {
if([operation.historyItems count] > 0) {
//display data here
} else {
//display no data alert
}
}
-(void)loadHistoryFailed:(GetHistoryOperation*)operation {
//show failure alert
}
And my operations generally looks something like this:
-(void)main {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSError* error = nil;
NSString* postData = [self postData];
NSDictionary *dictionary = [RequestHelper performPostRequest:kGetUserWalkHistoryUrl:postData:&error];
if(dictionary) {
NSNumber* isValid = [dictionary objectForKey:#"IsValid"];
if([isValid boolValue]) {
NSMutableArray* tmpDays = [[NSMutableArray alloc] init];
NSMutableDictionary* tmpWalksDictionary = [[NSMutableDictionary alloc] init];
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyyMMdd"];
NSArray* walksArray = [dictionary objectForKey:#"WalkHistories"];
for(NSDictionary* walkDictionary in walksArray) {
Walk* walk = [[Walk alloc] init];
walk.name = [walkDictionary objectForKey:#"WalkName"];
NSNumber* seconds = [walkDictionary objectForKey:#"TimeTaken"];
walk.seconds = [seconds longLongValue];
NSString* dateStart = [walkDictionary objectForKey:#"DateStart"];
NSString* dateEnd = [walkDictionary objectForKey:#"DateEnd"];
walk.startDate = [JSONHelper convertJSONDate:dateStart];
walk.endDate = [JSONHelper convertJSONDate:dateEnd];
NSString* dayKey = [dateFormatter stringFromDate:walk.startDate];
NSMutableArray* dayWalks = [tmpWalksDictionary objectForKey:dayKey];
if(!dayWalks) {
[tmpDays addObject:dayKey];
NSMutableArray* dayArray = [[NSMutableArray alloc] init];
[tmpWalksDictionary setObject:dayArray forKey:dayKey];
[dayArray release];
dayWalks = [tmpWalksDictionary objectForKey:dayKey];
}
[dayWalks addObject:walk];
[walk release];
}
for(NSString* dayKey in tmpDays) {
NSMutableArray* dayArray = [tmpWalksDictionary objectForKey:dayKey];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"startDate" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray* sortedDayArray = [dayArray sortedArrayUsingDescriptors:sortDescriptors];
[sortDescriptor release];
[tmpWalksDictionary setObject:sortedDayArray forKey:dayKey];
}
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:NO selector:#selector(localizedCompare:)];
self.days = [tmpDays sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
self.walks = [NSDictionary dictionaryWithDictionary:tmpWalksDictionary];
[tmpDays release];
[tmpWalksDictionary release];
[dateFormatter release];
self.success = YES;
} else {
self.success = NO;
self.errorString = [dictionary objectForKey:#"Error"];
}
if([dictionary objectForKey:#"Key"]) {
self.key = [dictionary objectForKey:#"Key"];
}
} else {
self.errorString = [error localizedDescription];
if(!self.errorString) {
self.errorString = #"Unknown Error";
}
self.success = NO;
}
[pool release];
}
-(NSString*)postData {
NSMutableString* postData = [[[NSMutableString alloc] init] autorelease];
[postData appendFormat:#"%#=%#", #"LoginKey", self.key];
return [NSString stringWithString:postData];
}
----
#implementation RequestHelper
+(NSDictionary*)performPostRequest:(NSString*)urlString:(NSString*)postData:(NSError**)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:#"%#/%#", kHostName, urlString]];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
[urlRequest setHTTPMethod:#"POST"];
if(postData && ![postData isEqualToString:#""]) {
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
[urlRequest setHTTPBody:[postData dataUsingEncoding:NSASCIIStringEncoding]];
[urlRequest setValue:postLength forHTTPHeaderField:#"Content-Length"];
[urlRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
}
NSURLResponse *response = nil;
error = nil;
NSData *jsonData = [NSURLConnection sendSynchronousRequest:(NSURLRequest *)urlRequest returningResponse:(NSURLResponse **)&response error:(NSError **)&error];
NSString *jsonString = [[NSString alloc] initWithBytes: [jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
NSLog(#"JSON: %#",jsonString);
//parse JSON
NSDictionary *dictionary = nil;
if([jsonData length] > 0) {
dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:error];
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
return dictionary;
}
If I have the autorelease pool in place, the crash occurs on [pool release]. If I don't, then the crash just looks to appear in the main.m method, and I don't seem to get any useful information. It's difficult to track down when I have to wait 10 mins in between every test!
If anyone can offer any clues or directions to go, that'd be much appreciated.
It's almost certain you're overreleasing something in your code, seeing that the crash is occurring during a [pool release] (There's a autorelease pool in the main method as well).
You can find it using Xcode - use build and analyze to have the static analyser pinpoint potential problems. Run it and post the results.
try this:
http://cocoadev.com/index.pl?NSZombieEnabled
also, you should avoid:
1) calling UIKit methods from secondary threads
2) making (synchronous) url requests from the main thread.
you must be doing one in any case in RequestHelper's performPostRequest method.
My guess is this section
GetHistoryOperation* operation = (GetHistoryOperation*)object;
if(operation.success) {
[self performSelectorOnMainThread:#selector(loadHistorySuceeded:) withObject:operation waitUntilDone:YES];
} else {
[self performSelectorOnMainThread:#selector(loadHistoryFailed:) withObject:operation waitUntilDone:YES];
}
If the sleep happens at a bad point here, you have an object being passed to another thread. I'd find a way around having to pass the operation as the object.
This is a really old question, so sorry for the dredge, but there is no accepted answer.
I was also getting a EXC_BAD_ACCESS on NSOperationQueue -addOperation for seemingly no reason, and after a few days of hunting down memory leaks, and turning on all the debugger options i could find (malloc guard, zombies) and getting nothing, I found an NSLog warning that said: "[NSoperation subclass] set to IsFinished before being started by the queue."
When I modified my base operation subclass, so that its -cancel function only set (IsRunning = NO) and (IsFinished = YES) IF AND ONLY IF (IsRunning == YES), NSOperationQueue stopped crashing.
So if you're ever calling NSOperationQueue -cancelAllOperations, or you're doing that manually (i.e. for (NSOperation *op in queue.allOperations) ) double check to make sure that you don't set IsFinished on those operations in your subclass implementation.

how to compare a NSURLconnection http response data with a string value in iphone?

I want to do an activation module which will send a http request with a PIN number and then read the response. If the response is "OK", it opens up with a main menu. The problem is that I am receiving the response as "OK" but I am unable to compare it with a NSString #"OK". How to compare the http response with a string?
Here is my piece of code:
-(IBAction) submitPINAction:(id) sender
{
printf("inside submit btn");
mydata = [NSMutableData alloc];
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:#"http://192.168.100.3/WWTF/activationApp.php?PIN=11111"]
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
if(connection)
{
mydata = [[NSMutableData data] retain];
}
else
{
//Handle error : Not received data
printf("No internet connection");
}
}
-(void)connection:(NSURLConnection *)theConnection
didReceiveData:(NSData *)incrementalData {
printf("data received");
if (mydata==nil) {
mydata =
[[NSMutableData alloc] initWithCapacity:2048];
}
[mydata appendData:incrementalData];
NSString *temp = [[NSString alloc] initWithData:mydata encoding:NSASCIIStringEncoding];
NSString *string1 = #"OK";
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if([string1 isEqualToString:temp]){ // HERE IS THE PROBLEM, THE STRINGS ARE NOT GETTIN COMPARED
[prefs setBool:TRUE forKey: #"activationKey"];
// show the main menu
mainMenuController *mmC = [[mainMenuController alloc]initWithNibName:#"mainMenu" bundle:[NSBundle mainBundle]];
self.mmainMenuController = mmC;
[mmC release];
[self.view addSubview:[mmainMenuController view]];
}
else{
printf("in else");
[prefs setBool:FALSE forKey: #"activationKey"];
//show an alert
UIAlertView *alertActivationFail = [[UIAlertView alloc] initWithTitle:#"Activation Failed!" message:#"PIN is Incorrect" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertActivationFail show];
[alertActivationFail release];
}
}
I would use the following line, to see that the response is actually the OK string, cause it may contain white space or other characters.
NSLog(#"string1 = '%#' temp = '%#'", string1, temp);
put this line before the if statement like this...
NSString *string1 = #"OK";
NSLog(#"string1 = '%#' temp = '%#'", string1, temp);
if([string1 isEqualToString:temp]){ // HERE IS THE PROBLEM, THE STRINGS ARE NOT GETTIN COMPARED
If extra whitespace is the reason why the comparison is failing then you can trim whitespace from you string by using the following method:
+(NSString *)trim:(NSString *)value {
return [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
Another thing I would make sure is that you've received all the data before you check for the string. It looks like you do the string checking in didReceiveData, but it may make more sense to do the check in connectionDidFinishLoading after the data is complete.
Thank you Korros and danvin for helping me out.
The problem was indeed with whitespaces.
I trimmed the whitespaces as you said and it worked.
and Thanks stackoverflow.com . It is really a great forum.I find helpful ansers for all iPhone related topics, at the same time it also helps other platform as well i believe.