Adding multiple strings to a string - xcode

How do I add multiple strings to a string ?
Whats the easiest way to do that ?
If I don't want to create a new line of code every time I add something to a string, I'd like to do something like that :
NSString *recipeTitle = [#"<h5>Recipe name: " stringByAppendingFormat:recipe.name, #"</h5>"];
NSLog(#"%#", recipeTitle);
// This shows: <h5>Recipe name: myrecipe
// Where's the </h5> closing that header ? It will only show up with the next line of code
recipeTitle = [recipeTitle stringByAppendingFormat:#"</h5>"];
//my problem is that will result in more than 1k lines of programming
Do I have to necessarily add a new line appending the appended every time ?
Is there a faster/more productive way to do that ?
I'm trying to compose the email body with my tableview in it and that will result in a huge set of programming lines. Isthere anybody that could give me any hint or anything better than composing a huuuge string just so i can populate my email body with a table containing my tableview data ?
Any help to make this more productive is appreciated. Thanks !
Carlos Farini.
// After working on it a bit i got:
-(IBAction)sendmail{
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
[composer setMailComposeDelegate:self];
NSString *recipeTitle = #"<h5>Recipe name: ";
recipeTitle = [recipeTitle stringByAppendingFormat:recipe.name];
recipeTitle = [recipeTitle stringByAppendingFormat:#"</h5>"];
NSString *ingredientAmount = #"";
NSString *ingredientAisle = #"";
NSString *ingredientTitle = #"";
NSString *tableFirstLine = #"<table width='90%' border='1'><tr><td>Ingredient</td><td>Amount</td><td>Aisle</td></tr>";
NSString *increments = #"";
int i=0;
for (i=0; i < [ingredients count]; i++) {
Ingredient *ingredient = [ingredients objectAtIndex:i];
ingredientTitle = ingredient.name;
ingredientAmount = ingredient.amount;
ingredientAisle = ingredient.aisle;
increments = [increments stringByAppendingFormat:recipeTitle];
increments = [tableFirstLine stringByAppendingFormat:#"<tr><td>"];
increments = [increments stringByAppendingFormat:ingredientTitle];
increments = [increments stringByAppendingFormat:#"</td><td>"];
increments = [increments stringByAppendingFormat:ingredientAmount];
increments = [increments stringByAppendingFormat:#"</td><td>"];
increments = [increments stringByAppendingFormat:ingredientAisle];
increments = [increments stringByAppendingFormat:#"</td></tr>"];
if (i == ([ingredients count]-1)) {
//IF THIS IS THE LAST INGREDIENT, CLOSE THE TABLE
increments = [increments stringByAppendingFormat:#"</table>"];
}
}
NSLog(#"CODE:: %#", increments);
if ([MFMailComposeViewController canSendMail]) {
[composer setToRecipients:[NSArray arrayWithObjects:#"123#abc.com", nil]];
[composer setSubject:#"subject here"];
[composer setMessageBody:increments isHTML:YES];
[composer setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentModalViewController:composer animated:YES];
[composer release];
}else {
[composer release];
}
}
But then again, it's showing just one row in the table. What am I doing wrong here ?

How about something like this:
NSString *recipeTitle = [NSString stringWithFormat:#"<h5>Recipe name: %# </h5>", recipe.name];

Related

Sorting NSJSON arrays aren't working properly

In my json file I have a title, subtitle, and url.
I sort the title to set the items alphabetically, but the url isn't sorted with the title and I don't know why.
This is what i've done:
NSDictionary *allDataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
NSArray *arrayOfItems = [allDataDictionary objectForKey:#"items"];
for (NSDictionary *diction in arrayOfItems) {
NSString *titles = [diction objectForKey:#"title"];
NSString *station = [diction objectForKey:#"url"];
[jsonArray addObject:titles];
[jsonStations addObject:station];
// SORT JSON
NSArray *sortedArray;
sortedArray = [jsonArray sortedArrayUsingComparator:^NSComparisonResult(NSString *title1, NSString *title2)
{
if ([title1 compare:title2] > 0)
return NSOrderedDescending;
else
return NSOrderedAscending;
}];
[jsonArray setArray:sortedArray];
When I press the first item in the tableView, I get get the url from a total diffrent title.
What should I do to get the title to match the url in the tableView?
First of all this seems like a strange way of sorting, you should use a dictionary instead of 2 arrays otherwise things get messy very quickly.
Secondly you need to pass your sortedArray to the table instead of the jsonArray currently it seems to be just trying to reset the jsonArray.
I would create one method to handle it like this (I have stripped some of your sorting script to simplify this)
-(NSArray *)sortContentWithJSONData {
NSDictionary *allDataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
NSArray *arrayOfItems = [allDataDictionary objectForKey:#"items"];
NSArray *sortedArray = [NSSortDescriptor sortDescriptorWithKey:#"title" ascending:false];
NSMutableArray *outputArray = [[NSMutableArray alloc] init];;
for (NSDictionary *diction in arrayOfItems) {
NSString *titles = [diction objectForKey:#"title"];
NSString *station = [diction objectForKey:#"url"];
[outputArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:titles, #"title", station, #"station", nil]]
}
return [outputArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortedArray]];
}
Then you could set a global array and access it in your table view using the following...
NSArray *tableContent = [self sortContentWithJSONData];
Hope that clears things up a bit :)

How to increment a 'score' during fast enumeration

I have the following code which I would like to use to check user answers and output a score (out of 5). I use a plist with the answers in and check the textField.text against it. What I'm struggling with is: how to get an output score as a total using this method?
- (IBAction)checkAnswers:(UITextField *)textField
{
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"7A Cells Microscopes 3" ofType:#"plist"];
NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:path2];
NSString *tester = [NSString stringWithFormat:#"%i", textField.tag];
// NSDictionary *secondDict = [dictionary valueForKey:tester];
// NSString *answer = [secondDict valueForKey:#"Answer"];
// if ([textField.text isEqualToString:[[dictionary valueForKey:tester] valueForKey:#"Answer"]]) {
// NSLog(#"YAY");
// }
NSArray *allTextFields = [[NSArray alloc] initWithObjects:eyepiece, objectiveLens, focussingKnobs, stage, mirror, nil];
for (textField in allTextFields) {
int x = 0;
if ([textField.text isEqualToString:[[dictionary valueForKey:tester] valueForKey:#"Answer"]]) {
x++;
NSLog(#"%i", x);
}
}
Any help would be much appreciated!
Many thanks.
Assuming the rest of your code is good, just move int x = 0; outside the for loop. The way you have it coded x is reset to 0 on every loop... so it never counts.

MKMapAnnotations didSelectAnnotationView not responding

I am creating an app that pulls data from a server and pinpoints the different houses on a map. My problem is that it does display the annotations but when I click on them they do not respond
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
I put my annotations in an array by:
int s;
self.mapAnnotations = [[NSMutableArray alloc] init];
for(s=0; s < numberOfAnnotations; s++)
{
//NSDictionary *dict2 = [parser objectWithString:[[arrayOfResults objectAtIndex:0] description]];
CLLocationDegrees daLong = [[[[[arrayOfResults objectAtIndex:s] objectForKey:#"map"] objectForKey:#"longitude"] description] floatValue];
CLLocationDegrees daLat = [[[[[arrayOfResults objectAtIndex:s] objectForKey:#"map"] objectForKey:#"latitude"] description] floatValue];
/*self.customAnnotation = [[BasicMapAnnotation alloc] initWithLatitude:daLat andLongitude:daLong];
[self.mapView addAnnotation:self.customAnnotation];*/
BasicMapAnnotation *m = [[BasicMapAnnotation alloc] initWithLatitude:daLat andLongitude:daLong];
[self.mapAnnotations addObject:m];
}
[self.mapView addAnnotations:self.mapAnnotations];
NSLog(#"this number of annotations %d", [self.mapAnnotations count]);
I also noticed when I created a separate house to place on the map in my viewDidLoad:
self.normalAnnotation = [[BasicMapAnnotation alloc] initWithLatitude:38 andLongitude:-90.2045];
self.normalAnnotation.title = #" ";
[self.mapView addAnnotation:self.normalAnnotation];
It did work when I clicked on it, but the ones passed through the array didn't work.
Can anyone help me figure out why it's not responding?
That's because annotations should have a title for them to display a callout. In your for loop, set the title property like you did with self.normalAnnotation.title = #" ".

Set a UITextField from an NSArray

I have tried many variations with no luck. I can NSLog the array and I get this:
2011-07-17 00:54:54.886 Widgets[13444:207] <Widget: 0x5e2aad0> (entity: Widget; id: 0x5e0d8e0 <x-coredata://E64A0BCE-2344-4EE1-89CC-164ACD8995D6/Recipe/p115> ; data: {
success = 1;
coconutscarried = nil;
name = "African Swallow";
uidnumber = "105 ";
})
How can I simple set a text field?
Pardon the mess but this is an assortment of code I have tried (messy). The array and text field have been set up in .h/m and bound in IB
- (void)viewDidLoad {
[super viewDidLoad];
//NSLog(#"%#",[[swallowArray name] text]); // doesnt work
//NSLog(#"The string at index is %#.", [self.swallowArray objectAtIndex:0]);//nope...
for (int i = 0; i < [swallowArray count]; i++) {
//nameTextField.text = [[swallowArray objectAtIndex:i] uidnumber];
//NSLog(#"%#",swallowArray.name);
//}
//nameTextField.text = [[swallowArray objectAtIndex:0] uidnumber];
//NSString* strRate = [[swallowArray object] uidnumber];
nameTextField.text = [nameTextField.text stringByAppendingString:[NSString localizedStringWithFormat:#", %#", [[swallowArray objectAtIndex:i] name]]];
}
and many more. This has got to be dead simple, but I am kind of a noob.
thanks!
bo
after 5 hours of searching, I post here, and find the answer in literally five minutes!
NSString *nameFromArray = [NSString stringWithFormat:#"%#", [eventArray valueForKey:#"name"]];
NSLog(#"%#", nameFromArray);
Hope this helps someone else!

returning an NSObject - bad exec

I've been struggling with a problem that I hope someone can help me with.
I have Class called 'GameObjectDefinitionTable', where I set all my object properties, which is in another class called 'Product'. In my 'HelloWorldScene' I allocate 'GameObjectDefinitionTable' which in turn creates several 'Product's. Like this:
HelloWorldScene -> GameObjectDefinitionTable -> Product
I then want to return a 'Product' to 'HelloWorldScene. But here is where I get problems. Some code:
HelloWorldScene:
GameObjectDefinitionTable *god = [[GameObjectDefinitionTable alloc]init];
Product* currentProduct = [god getProductWithNum:0];
NSLog(#"currenProduct (name): %#",currentProduct.name); //Crash
GameObjectDefinitionTable:
-(void) createProducts {
Product *product;
for (int i=0; i<[allProductsWithDefinitions count];i++ ) {
product = [[Product alloc]init];
product.name = [[allProductsWithDefinitions objectAtIndex:i] objectAtIndex:0];
product.density = [[[allProductsWithDefinitions objectAtIndex:i] objectAtIndex:1] floatValue];
product.scoreValue = [[[allProductsWithDefinitions objectAtIndex:i] objectAtIndex:2] intValue];
product.fileName = [[allProductsWithDefinitions objectAtIndex:i] objectAtIndex:3];
[products addObject:product];
[product release];
}
[allProductsWithDefinitions release];
}
-(Product *) getProductWithNum:(int)tNum {
Product *tempProduct;
tempProduct = [products objectAtIndex:tNum];
return tempProduct;
[tempProduct release];
}
The arrays and all in 'GameObjectDefinitionTable' is working fine if I log in that class.
Would be really grateful for an answer :)
Is it the case you need something like:
- (Product *)getProductWithNum:(int)tNum
{
Product *tempProduct = [[products objectAtIndex:tNum] retain];
return [tempProduct autorelease];
}
Product *tempProduct;
tempProduct = [products objectAtIndex:tNum];
return tempProduct;
[tempProduct release];
Is that what you mean to have? You kind of have two big problems cancelling each other out here. The [tempProduct release]; line is unreachable. The second, if you were to actually execute [tempProduct release]; before the return, you would be releasing the memory, and then accessing the currentProduct.name property of what is essentially a dangling pointer. This illegal memory access could cause your Bad Exec.
Since you are not allocating, copying, or retaining tempProduct, you must NOT release it. Why not just a simple return [products objectAtIndex:tNum];?

Resources