Update value in array - objective-c

How do I update a single value in each row of my array?
For example I have an array created from an SQL DB with the following columns.
Name
Address
Lat
Long
Distance
Distance is initially set to 0 until calculated from the Lat/Long. I want to update that 0 with the calculated distance.
Every example I've found doesn't show how to update a single column per row.
NSMutableArray *barInfo = [BarDatabase database].barInfo;
for (Bars *info in barInfo) {
NSLog(#"%#, %#, %#, %#, %#", info.barName, info.barAddress, info.Lat, info.Long, info.cachedDist);
NSString *strLat = info.Lat;
NSString *strLong = info.Long;
CLLocation *barLocation = [[CLLocation alloc] initWithLatitude:[strLat doubleValue] longitude:[strLong doubleValue]];
CLLocationDistance bdistance = [currentLat distanceFromLocation:barLocation]/1000;
[barInfo addObject:bdistance];
}
I'm using an NSMutableArray because I can't figure out how to modify the Distance field in the NSArray. I know Apple states this is possible, but I can't find it.

Related

So I've stored an NSDictionary object in an NSMutableArray, how do I know use the NSDictionary keys to grab these objects out of the array?

I have two UISlider's that represent minimum and maximum prices of items. I am passing these as well as other various data back to the previous controller.
I've used a protocol method and set the previous controller as a delegate to make it possible to pass values back to the controller.
I can easily grab the other objects out of the array because they're strings. I just use:
[_finalSelectionForRefinement containsObject:#"size"];
This is what I do in pushed controller:
// create dictionary with keys minimum and maximum that hold the
// position of the slider as a float
_dictionaryWithSliderValues =
[[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithFloat:_minSliderPosition], #"minimum",
[NSNumber numberWithFloat:_maxSliderPosition], #"maximum", nil];
// store this in the array that is retrieved in previous controller
[_finalSelectionForRefinement addObject:_dictionaryWithSliderValues];
My question is how do I now use the minimum and maximum keys to grab the slider position float objects?
Thought I could use NSPredicate but the examples I've been coming across on blogs as well as youTube are of no help to my specific needs.
Would appreciate some help here
Regards
UPDATE - Short snipped of method in previous controller where I need to retrieve the slider minimum and maximum values:
-(PFQuery *)queryForCollection
{
PFQuery *query = [PFQuery queryWithClassName:#"Garments"];
if (_selectedRowInFilterPicker == 0) {
NSLog(#"ORDER BY RECOMMENDED");
[query orderByDescending:#"recommended"];
} else if (_selectedRowInFilterPicker == 1) {
NSLog(#"ORDER BY NEWEST ITEMS");
[query orderByDescending:#"createdAt"];
} else if (_selectedRowInFilterPicker == 2) {
NSLog(#"ORDER BY DESCENDING USING PRICE");
[query orderByDescending:#"price"];
} else if (_selectedRowInFilterPicker == 3) {
NSLog(#"ORDER BY ASCENDING USING PRICE");
[query orderByAscending:#"price"];
}
if ([_selectionFromRefineResultsController count] > 0) {
NSLog(#"Selection FROM REF MADE");
// Gender
if ([_selectionFromRefineResultsController containsObject:#"Male"]) {
[query whereKey:#"gender" equalTo:#1];
}
if ([_selectionFromRefineResultsController containsObject:#"Female"]) {
[query whereKey:#"gender" equalTo:#2];
}
}
// Here I need to check there is a minimum or maximum value in the array
// If there is I can user [query whereKey:#"price" greaterThan:MINVAL] and MAXVAL
// This will return items within the correct price range.
This queryForCollection method is called from within another method called performQuery which is called when the button of the second controller is tapped to pass data back to the controller that pushed it in the first place.
You should look at the documentation for NSMutableArray , NSArray and NSDictionary
Which will explain the instance methods for each.
But in a nutshell any object that you add should be in a NSDictionary so it has a value and a key. This includes any of your strings. Doing so simplifies how you search by using keys.
If the NSMutableArray contains objects that are not KVC then you will I think find it harder it go through the objects in one sweep.
Because NSmutableArray inherites from NSArray you can then use instance method valueForKey: on a NSmutableArray whose objects values or objects objects values have keys.
valueForKey:
Returns an array containing the results of invoking
valueForKey: using key on each of the array's objects.
(id)valueForKey:(NSString *)key
Rough Example:
NSMutableArray * finalSelectionForRefinement =[[NSMutableArray alloc]init];
NSDictionary *dictionaryWithSliderValues = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithFloat:10], #"minimum", [NSNumber numberWithFloat:20], #"maximum", nil];
NSDictionary *stringValues = [[NSDictionary alloc] initWithObjectsAndKeys:#"the-size", #"size", #"the-hight", #"hight", nil];
[finalSelectionForRefinement addObject:dictionaryWithSliderValues];
[finalSelectionForRefinement addObject:stringValues];
NSLog(#"finalSelectionForRefinement = %#", [finalSelectionForRefinement valueForKey:#"maximum"] );
First off, you can of store everything in one NSDictionary which makes more sense. But I wanted to show you that the valueForKey: will search within each.
The other thing is valueForKey: will return an NSArray containing the results. any objects that it finds that do not match the key you are looking for will be returned as an NSNull object. i.e
finalSelectionForRefinement = (
20,
"<null>"
)
So you would need to still single your value out. One way is use a objectEnumerator like this:
NSEnumerator *enumerator = [[finalSelectionForRefinement valueForKey:#"maximum"] objectEnumerator];
id anObject;
while (anObject = [enumerator nextObject]) {
if(![anObject isKindOfClass:[NSNull class]])
{
NSLog(#"anObject = %#", anObject);
}
}
Which should return:
anObject = 20
There are most likely better ways of doing this. All of the above is just to give you one idea. And I suspect you could cut out a lot of the code by using bindings.
(also note this answer was being constructed before you question update)

objc Separating tuples

ran into a simple objc problem and need some help. I'm sending a query to a server that gives me back a tuple wrapped in jSON. Just using the dictionary to sort everything out.
- (void)viewDidLoad
{
[super viewDidLoad];
Nodes *node = [Nodes new];
NSDictionary *jsonDict = [node nodeActivityforNode:#"17" withDates:nil and:nil];
NSDictionary *jsonActivityDict = [jsonDict objectForKey:#"activity"];
NSLog(#"activity?: %#", jsonActivityDict);
}
and then heres the debug dump
activity?:
(
(
"2013-05-21 16:58:32",
0
),
(
"2013-05-21 16:58:15",
0
),
(
"2013-05-21 16:57:59",
0
),
I'm trying to split up the comma separated values so I can put them in individual int and string objects but just cant think of how to get in there. Any help would be appreciated. Thanks!
The "activity" data looks like an array of arrays, not a dictionary. If you know you will always get three pairs of values and you want those 6 values put into 6 separate variables then you could do this:
NSDictionary *jsonDict = [node nodeActivityforNode:#"17" withDates:nil and:nil];
NSArray *jsonActivities = [jsonDict objectForKey:#"activity"];
NSString *date1 = jsonActivities[0][0];
int int1 = [jsonActivities[0][1] intValue];
NSString *date2 = jsonActivities[1][0];
int int2 = [jsonActivities[1][1] intValue];
NSString *date3 = jsonActivities[2][0];
int int3 = [jsonActivities[2][1] intValue];
Note that this code will crash if there are less than 3 sets of pairs or if any of those three "pairs" only has one value instead of two.

Bug in my code using NSArray crashes

I'm making a code which shows the names of people on a list.
The list is different for each date, so my problem is when there is only like 1 or no people signed and I make an array with index beyond the limit of people, it crashed. I know that this happens because the array is empty, but how do I make the code ignore empty arrays?
I have tried to make an "if" that count the number of arrays and then decide to post the array or just post no name. But it doesn't work like this, I still get the out of bounds exception.
How should I manage empty arrays?
My code:
NSString *html = [request2 responseString];
NSMutableArray *arr2 = [html componentsSeparatedByString:#"vagter"];
NSString *html1 = [arr2 objectAtIndex:1];
//name1
NSMutableArray *arr3 = [html1 componentsSeparatedByString:#"<td><font color=#ffffff>"];
NSString *html2 = [arr3 objectAtIndex:1];
NSMutableArray *arr4 = [html2 componentsSeparatedByString:#"</font></td>"];
NSString *html3 = [arr4 objectAtIndex:0];
_name.text = html3;
//name 2
NSMutableArray *arr5 = [html1 componentsSeparatedByString:#"<td><font color=#ffffff>"];
if ([arr5 count] > 4) {
NSString *html4 = [arr5 objectAtIndex:5];
NSMutableArray *arr6 = [html4 componentsSeparatedByString:#"</font></td>"];
NSString *html5 = [arr6 objectAtIndex:0];
_name.text = html5;
}
else
{
_name1.text = #"No name";
}
It should be:
if ([arr5 count] > 5) {
NSString *html4 = [arr5 objectAtIndex:5];
...
Indeed, index 5 will correspond to the sixth array item, so you have to have at least 6 objects in it.
Use the same pattern, if you want to check for the array bounds, in all cases.
The problem is that you expect the return from componentsSeparatedByString to return consistent results according to your expectations.
Clearly thats not working.
Array handling is simple. Dont ask for objects that arent there.
Check the count and only access indexes from 0 to count - 1;
If count is zero dont access anything.

Tableview cells does not display data when in integer format

My application has a sqlite database and i m using executeQuery methods to retrive and insert data.
Problem
I cannot assign integer values cells of tableview. It does not display data which is in integer format. i want to store integer values into a tableview and show sorted integer
data to user.
Here i am posting my code
1) in viewDidLoad i have retrieved integer values from database table "dummy" and taken it into an NSArray "Scores"
2) i have assigned a value of "highscore" which is an integer type to cell in "cellForRowAtIndexPath" Method of table view.Note that converting this data into NSString does not allow sorting.
But this shows no data in table cells when i run it.
1)
NSString *myDBnew = #"/Users/taxsmart/Documents/sqlite/atest.sql";
database = [[Sqlite alloc] init];
[database open:myDBnew];
Scores = [database executeQuery:#"SELECT * FROM dummy ORDER BY highscore DESC;"];
2)
cell.textLabel.text = [[Scores objectAtIndex:indexPath.row] valueForKey:#"highscore"];
What is Wrong?
Please Give Your Suggestions. Your Suggestions are most welcome.
You must assign an NSString* to cell.textLabel.text. Just embedd your ints into an NSString.
NSInteger highscore = [[Scores objectAtIndex:indexPath.row] valueForKey:#"highscore"];
cell.textLabel.text = [NSString stringWithFormat:#"%d", highscore];

Comparing Touch Coordinates

Is it possible to compare touch coordinates made by the users on the UIView to the one store in a plist or txt format? The argument looks like this;
if (user touch coordinate == touch coordinate stored in plist or text)
then
(do something)
else
(do something)
If possible in what format should i write the coordinates in the list and how to associate it inside the program?
thanks in advance and sorry if you find my question a bit noobie.
Not sure if there's a one-liner solution.
On a UITouch instance, the locationInView: method returns a CGPoint struct (x and y coordinates, both of type float). So you can store the x and y coordinates in your plist, then compare them with your current touch's x and y coordinates.
EDIT:
Also, when comparing the coordinates, you probably want to use the distance between the two points to determine when you have a "hit".
EDIT:
Below is sample code for loading and writing to a property list, where the values are based on a NSDictionary:
- (NSMutableDictionary *)loadDictionaryFromPList: (NSString *)plistName
{
NSString *plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
NSDictionary *immutableDictionary = [NSDictionary dictionaryWithContentsOfFile: plistPath];
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary: immutableDictionary];
return mutableDictionary;
}
- (void)saveDictionary: (NSDictionary *)mySettings toPList: (NSString *)plistName
{
NSString *plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
[mySettings writeToFile: plistPath atomically: YES];
}
The method to calculate the distance between the two locations of the UITouches:
-(CGFloat) distanceBetween: (CGPoint) point1 and: (CGPoint)point2
{
CGFloat dx = point2.x - point1.x;
CGFloat dy = point2.y - point1.y;
return sqrt(dx*dx + dy*dy );
}
And finally, the code that uses the values in the property list to determine if the user hit the previous location:
CGPoint currentTouchLocation = [currentTouch locationInView:self];
// Lookup last Touch location from plist, and handle case when current Touch matches it:
NSMutableDictionary *mySettings = [self loadDictionaryFromPList: #"MySettings"];
NSNumber *lastXCoordinate = [mySettings objectForKey:#"lastXCoordinate"];
NSNumber *lastYCoordinate = [mySettings objectForKey:#"lastYCoordinate"];
if (lastXCoordinate && lastYCoordinate)
{
CGPoint lastTouchLocation = CGPointMake([lastXCoordinate floatValue], [lastYCoordinate floatValue]);
CGFloat distanceBetweenTouches = [self distanceBetween: currentTouchLocation and: lastTouchLocation];
if (distanceBetweenTouches < 25) // 25 is just an example
{
// Handle case where current touch is close enough to "hit" previous one
NSLog(#"You got a hit!");
}
}
// Save current touch location to property list:
[mySettings setValue: [NSNumber numberWithFloat: currentTouchLocation.x] forKey: #"lastXCoordinate"];
[mySettings setValue: [NSNumber numberWithFloat: currentTouchLocation.y] forKey: #"lastYCoordinate"];
[self saveDictionary:mySettings toPList: #"MySettings"];
The functions you're probably looking for are NSStringFromCGPoint() and CGPointFromString().
But two touch coordinates will almost certainly never be the exact same. You should almost never be comparing CGFloats with ==, let alone ones you get from such an analog input as a finger touch. You need to compare whether they are "close enough." See this blog for a good example of how to measure the distance between two points. You want that result to be less than some value (epsilon, or "a small number") that is appropriate for your purposes.