fetching data from tableview cell? - cocoa-touch

God evening :-D
i have a a tableview,(using core data) i pub the cell with a "Todo" like: "5 mile Run" and i set the detailed text to #"points value #", X were x is a number set by a slider, and the same time u set name for the Todo.
i have put in a button in the cell, and called it add, and i want to be able to add that number in the detailed text to a "totalPoints" attribute in my core data model.
i can make a fetchRequest for the entity,but how do i make sure that i get that number, and how do i use simple math when the "pointValue" is stored in NSNumber object.
Update :
fixed it :-D
if u add a button to your cell, u can get that indexPath like this :
- (IBAction)buttonTapped:(id)sender {
if (![sender isKindOfClass: [UIButton class]]) return;
UITableViewCell *cell = (UITableViewCell *)[sender superview];
if (![cell isKindOfClass: [UITableViewCell class]]) return;
NSIndexPath *indexPath = [self.tableView indexPathForCell: cell];
// do something with indexPath.row and/or indexPath.section.
this fixed my app, and it´s now in beta testing :-P
Thanks for your help
Skov

In your sample code, there are a couple issues. First, when you are getting the values a, b and e you can just do this:
NSNumber *a = toDo.pointsValue;
(assuming that toDo.pointsValue is an NSNumber).
Secondly, in your if statement you are comparing the values of the pointers, not the values in the objects that the pointers point to.
This code should have the result you want (I assume you initialize toDo in some way) :
ToDo *toDo;
CGFloat x = [toDo.pointsValue floatValue] + [toDo.totalPoint floatValue];
//Note: it is better to use CGFloat rather than plain float
CGFloat y = [toDo.goodiesPoints floatValue];
if (x >= y)
{
[self performSelector:#selector(winView)
withObject:nil
afterDelay:0.5];
}
I am not sure exactly what you mean when you say "how do i make sure that i get that number". What number is "that number"?

Related

Section for point in a UITableView?

-[UITableView indexPathForRowAtPoint:] returns an index path given a CGPoint. However, it only works when the CGPoint lies exactly on a cell. If the point happens to be on the header or footer of a section, it returns nil.
Given a CGPoint, how can I get the section at that point which doesn't fail in the case of header/footer?
I ended up using the following extension method, which relies on -rectForSection:. Depending on your needs, you may want to use -rectForHeaderInSection: or -rectForFooterInSection: instead.
- (NSIndexPath *)xyz_indexPathForRowAtPoint:(CGPoint)point {
NSIndexPath *indexPath = [self indexPathForRowAtPoint:point];
if (indexPath) {
return indexPath;
}
for (NSInteger section = 0; section < [self numberOfSections]; section++) {
if (CGRectContainsPoint([self rectForSection:section], point)) {
return [NSIndexPath indexPathForRow:0 inSection:section];
}
}
return nil;
}
There doesn't seem to be a specific method for that.
If [UITableView indexPathForRowAtPoint:] returns nil, you could add or subtract a few pixels from the point's Y-coordinate (preferably the sum of the footer height and header height), and see if this method returns a value. If it does, you obtain a section number close to the original point, and use the - rectForSection: method or the - rectForFooterInSection: and - rectForHeaderInSection: methods to get the exact section.

(xcode objective-c) Array - finding a center of a object in an array

I'm pretty nooby when it comes to Xcode but here goes.
I have an NSArray with 5 UIImageView's, I have a script which will pick a random UIImageView, but I need it to then output the center of the image that was chosen.
My code looks like this:
NSMutableArray *Invader = [[NSMutableArray alloc] init];
[Invader addObject:H1];
[Invader addObject:H2];
[Invader addObject:H3];
[Invader addObject:H4];
[Invader addObject:H5];
Then like this to choose where to move a new UIImageView to:
if (FIRE1 == YES){
NSObject *Inv1 = [Invader randomObject]; //randomObject picks a random Invader
InvaderBullet1.hidden = NO;
InvaderBullet1.center = CGPointMake(Inv1.center.x, Inv1.center.y)
}
The error it's giving me is Property 'center' not found on object of type 'NSObject *'
I'm hoping this makes sense to anyone and that anyone can help me.
Thanks
NSObject obviously doesn't have a center property. Though you're not adding NSObjects to your array, you're adding (I assume) UIImageViews. So if you're adding UIImages, you can remove UIImages as well.
if (FIRE1 == YES){
NSObject *Inv1 = [Invader randomObject];
if ([Inv1 isKindOfClass:[UIImageView Class]]) //randomObject picks a random Invader
((UIImageView*)InvaderBullet1).hidden = NO;
((UIImageView*)InvaderBullet1).center = CGPointMake(Inv1.center.x, Inv1.center.y)
}
You simply need to specify the correct type for your variable:
if (FIRE1 == YES){
UIImageView *Inv1 = [Invader randomObject]; //randomObject picks a random Invader
InvaderBullet1.hidden = NO;
InvaderBullet1.center = CGPointMake(Inv1.center.x, Inv1.center.y)
}
This is assuming that your randomObject method (looks like a category method on NSArray) has a return type of id. If its return type is NSObject * then you need to do a cast:
UIImageView *Inv1 = (UIImageView *)[Invader randomObject]; //randomObject picks a random Invader
(Minor note: I recommend to stick to the established naming conventions. In this case: variables usually start with a lower-case character. You're doing other people that need/want to work with your code a favor.)

indexOfObjectIdenticalTo: returns value outside of array count

I'm currently working on an app that populates a UITableView with items from a MPMediaItemCollection. I'm trying to add a UITableViewCellAccessoryCheckmark to the row that matches the title of the currently playing track.
I've done so by creating a mutable array of the track titles, which are also set for my cell's textLabel.text property. (for comparison purposes)
Note: This is all done in - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
MPMediaItem *mediaItem = (MPMediaItem *)[collectionMutableCopy objectAtIndex: row];
if (mediaItem) {
cell.textLabel.text = [mediaItem valueForProperty:MPMediaItemPropertyTitle];
}
[mutArray insertObject:cell.textLabel.text atIndex:indexPath.row];
To the best of my knowledge this all works fine except for the below. At this point, I am trying to get the index of the currently playing tracks title and add the UITableViewCellAccessoryCheckmark to that row.
if (indexPath.row == [mutArray indexOfObjectIdenticalTo:[mainViewController.musicPlayer.nowPlayingItem valueForProperty:MPMediaItemPropertyTitle]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
Getting to my question, I added all of the above (mostly irrelevant) code because I'm stumped on where I went wrong. When I log indexOfObjectIdenticalTo: it spits out "2147483647" every time, even though there are never more than 5 objects in the array. But why?
If anyone has any tips or pointers to help me fix this it would be greatly appreciated!
2147483647 just mean the object is not found.
From the documentation of -[NSArray indexOfObjectIdenticalTo:]:
Return Value
The lowest index whose corresponding array value is identical to anObject. If none of the objects in the array is identical to anObject, returns NSNotFound.
and NSNotFound is defined as:
enum {
NSNotFound = NSIntegerMax
};
and 2147483647 = 0x7fffffff is the maximum integer on 32-bit iOS.
Please note that even if two NSString have the same content, they may not be the identical object. Two objects are identical if they share the same location, e.g.
NSString* a = #"foo";
NSString* b = a;
NSString* c = [a copy];
assert([a isEqual:b]); // a and b are equal.
assert([a isEqual:c]); // a and c are equal.
assert(a == b); // a and b are identical.
assert(a != c); // a and c are *not* identical.
I believe you just want equality test instead of identity test, i.e.
if (indexPath.row == [mutArray indexOfObject:[....]]) {
Looking at the docs for NSArray
Return Value
The lowest index whose corresponding array value is identical to anObject. If none of the objects in the array is identical to anObject, returns NSNotFound.
So you should probably do a check
NSInteger index = [array indexOfObjectIdenticalTo:otherObject];
if (NSNotFound == index) {
// ... handle not being in array
} else {
// ... do your normal stuff
}

how to access the labels using tags in objective-c

I am implementing an iphone application.Which is a UItableview.It has two sections.Three labels are added to all the cells in section-I.I have given tags 1,2,3 for those 3 labels when adding to the cells.Now I want to get the values from label3 from all the cells from section-I and I would like to add all the float values and display the total in another label which is in section-II.I read that I should give different tags for different cell's label3(label with tag-3).How is it possible please guide me.I have float values in the label3.I wanna add all the values and present the result in section-II.Please help me with some reference.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString* curItem = [self.finalItems objectAtIndex:indexPath.row];
NSString* curQuantity = [self.finalPrices objectAtIndex:indexPath.row];
NSString* priceStr = [self fetchDishRecordswithpredicate:curItem];
NSMutableString* priceValStr = [NSMutableString stringWithString:priceStr];
[priceValStr replaceCharactersInRange:NSMakeRange(0, 1) withString:#""];
float totalPrice = [curQuantity floatValue]*[priceValStr floatValue];
UILabel *lblTemp1 = (UILabel *)[cell viewWithTag:1];
UILabel *lblTemp2 = (UILabel *)[cell viewWithTag:2];
UILabel *lblTemp3 = (UILabel *)[cell viewWithTag:3];
switch (indexPath.section) {
case 0: {
lblTemp1.text = curItem;
lblTemp2.text = curQuantity;
lblTemp3.text = [NSString stringWithFormat:#"$ %0.2f", price];
} break;
case 1: {
lblTemp1.text = #"Your Total:";
lblTemp3.text = #"How can I get Total here";
} break;
}
return cell;
}
It should never be necessary to get the value of a label, whether it's part of a table cell or some other kind of view. The user can't modify a label -- they're for display only. That means that the only way that a label can get a given value is for your program to set that value, and that in turn means that you've already got the data you need somewhere. That holds true for any kind of view other than controls that are used for getting input from the user.
The fact that you're looking to get values from labels probably means that you're using your views to store data, which is not a good practice. Views display data, but that data should be stored elsewhere in the program, typically in a data model (assuming you're following the MVC paradigm).
All that said, you can get the cell for a given row from your table using its -cellForRowAtIndexPath: method. From there, you can access the cells subviews using the usual -viewWithTag: method. You definitely don't need a unique set of tags for each cell -- you just need to get the cell for the row that you're interested in. However, keep in mind that a table usually only keeps the cells that are visible around; if you ask it for the cell for a row that's not visible, it'll probably have to create that cell, which in turn will involve asking the table's delegate (your own code!) for the cell. That's a pretty expensive way to ask yourself for data that you already have! ;-)

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.