i'm getting the distance of 2 points like this
[userLocation distanceFromLocation: annotationLocation] / 1000;
and setting this to the subtitle of a tableview like the image bellow
the question is, can i order this table by the distances (subtitle)?
Thanks!
and sorry for the bad english =x
You can order your UITableView's cells any way to want to, but you have to do it before showing them, when you create the table's data source. If you use an NSFetchResultsController, you can put the distance as the sort descriptor. And if you are using a simple NS(Mutable)Array, sort it before making it the table's source.
Like Chris said, you can do it with
NSSortDescriptor *titleSorter= [[NSSortDescriptor alloc] initWithKey:#"annotationLocation" ascending:YES];
If it is an NSArray what you are using, then:
[arrayOfObjects sortUsingDescriptors:[NSArray arrayWithObject:titleSorter];
and if it is an NSFetchResultsController:
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:titleSorter, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
Create an NSSortDescriptor to sort your rows:
NSSortDescriptor *titleSorter= [[NSSortDescriptor alloc] initWithKey:#"annotationLocation" ascending:YES];
[arrayOfObjects sortUsingDescriptors:[NSArray arrayWithObject:titleSorter];
Make an array with these distances, order it how you want and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *_cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (_cell == nil) {
_cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier] autorelease];
}
_cell.textLabel.text = #"Transcripts";
_cell.detailTextLabel.text = [yourArray objectAtIndex:indexPath.row];
return _cell;
}
well, something like that should do the trick.
Hope it helps
Assuming you have some certain objects holding a coordinate and put the objects in to an array locations, you can use a comparator block by doing:
locations = [locations sortedArrayUsingComparator: ^(id a, id b) {
CLLocationDistance dist_a= [[a objectsForKey:#"coordinate"] distanceFromLocation: userPosition];
CLLocationDistance dist_b= [[b objectsForKey:#"coordinate"] distanceFromLocation: userPosition];
if ( dist_a < dist_b ) {
return (NSComparisonResult)NSOrderedAscending;
} else if ( dist_a > dist_b) {
return (NSComparisonResult)NSOrderedDescending;
} else {
return (NSComparisonResult)NSOrderedSame;
}
}
You add this code to your viewWillAppear: to get updated locations each time you display the tableView.
Related
I am trying to fetch all categories, and their sub categories, and display them all in a table. I know how to fetch all categories, but I need to fetch all sub categories, and sort them by category using a fetch results controller. Any ideas of suggestions?
You can create a fetched results controller that fetches SubCategory entities and groups them into sections according to the Category:
// Fetch "SubCategory" entities:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"SubCategory"];
// First sort descriptor for grouping the cells into sections, sorted by category name:
NSSortDescriptor *sort1 = [NSSortDescriptor sortDescriptorWithKey:#"category.name" ascending:YES];
// Second sort descriptor for sorting the cells within each section:
NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObjects:sort1, sort2, nil];
self.fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:context
sectionNameKeyPath:#"category.name"
cacheName:nil];
[self.fetchedResultsController setDelegate:self];
NSError *error;
BOOL success = [self.fetchedResultsController performFetch:&error];
Then you can use the usual table view data source methods as described in the NSFetchedResultsController Class Reference.
This gives you a table view with one table view section for each category.
so, you have the categories in the fetchedResultsController.fetchedObjects
since each subCategory is essentially contained in the Category you can access each by calling [Category valueForKey:#"subCategory"
this will give you an NSSet that you can then sort out (to an NSArray) and use as data for your tableView.
It won't be contained in a fetchedResultsController though.
If you have the option u can do it in other way also if u like.
Take all The Category objects in arrayOfCategories
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection (NSInteger)section:
{
Category *cat = [ arrayOfCategories objectAtIndex:indexPath.row]
if(arrayToHoldObjects.count > 0)
{
[arrayToHoldObjects removeAllObject];
}
for(Subcategory *sub in Category.subcategory)
{
[arrayToHoldObjects addObject:sub];
}
return arrayToHoldObjects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Category *cat = [ arrayOfCategories objectAtIndex:indexPath.row]
if(arrayToHoldObjects.count > 0)
{
[arrayToHoldObjects removeAllObject];
}
for(Subcategory *sub in Category.subcategory)
{
[arrayToHoldObjects addObject:sub];
}
Subcategory *sub = [arrayToHoldObjects objectAtIndexPath.row]
for(int k =0 ; k < arrayToHoldObjects .count; k++)
{
// do what ever u like with sub
return cell;
}
}
I am adding object exercise to object session (as a relationship).
In a view, I want to fetch and display exercises for a particular session object.
Right now it is showing all exercises in the database rather than just for that session object.
The relationship between the two objects is called "exercises".
This is the current code I am using for the fetch if anyone can help me.
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Exercise" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
LogResultsViewController *logResultsTableViewController = [[LogResultsViewController alloc]init];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat: #"exercises = %#", logResultsTableViewController.selectedSession]];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
Updated Code:
- (void) viewDidLoad
{
NSSet *exercises = [self.selectedSession valueForKey:#"exercises"];
NSArray *sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"timeStamp" ascending:YES]];
NSArray *sorted = [exercises sortedArrayUsingDescriptors:sortDescriptors];
sorted = self.exerciseArray;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [exerciseArray count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [exerciseArray objectAtIndex:indexPath.row];
return cell;
}
When I NSLog the selectedSession, here is what it shows:
selectedSession: <Session: 0x7336940> (entity: Session; id: 0x7334f70 <x-coredata://17D44726-23F7-402F-9CBE-2EED96212E14/Session/p1> ; data: {
exercises = "<relationship fault: 0x5d34680 'exercises'>";
timeStamp = "2011-05-31 04:41:07 +0000";
Also, when I NSLog the NSSset called exercises, I get:
Relationship fault for (<NSRelationshipDescription: 0x711b370>), name exercises, isOptional 1, isTransient 0, entity Session, renamingIdentifier exercises, validation predicates (
), warnings (
), versionHashModifier (null), destination entity Exercise, inverseRelationship exercises, minCount 0, maxCount 0 on 0x7140790
Update:
Ok so I changed the code in cellForRowAtIndex to have
Exercise *exercise = (Exercise *)[exerciseArray objectAtIndex:indexPath.row];
cell.textLabel.text = exercise.name;
Now it shows the exercise name but it is showing the same list of exercises for all sessions, instead of just for the session to which it belongs to.
If your instances of Session have a relationship to instances of Exercise, you don't need to do another fetch to get the session's exercises. You can just follow the relationship and get them directly-- they'll be loaded automatically. From your code it looks like logResultsTableViewController.selectedSession is an instance of Session. If that's the case, you can get all of that session's exercies as follows (assuming the relationship is called exercises):
NSSet *exercises = [logResultsTableViewController.selectedSession valueForKey:#"exercises"];
You can then sort that NSSet as needed.
I am creating Travel guide app using core data. I have 4 entities CITY ,RESTAURANTS ,
HOTEL AND FAMOUS PLACES. City is connected with all other entity because one city may have number of restaurants , hotels and places. City entity has 3 attribute Name ,Image ,Description. I am able to display list restaurants of selected city.In Restaurant Entity I have 4 attribute Name, Description ,Address and phone no..Now I want to show
this attribute detail of selected restaurant(of selected city) in next view.But how can I access restaurant description in next view..
Here is my code.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSMutableArray *restaurants = [[NSMutableArray alloc]initWithArray:[city.cityTorestaurants allObjects]];
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc]initWithKey:#"Name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:nameDescriptor,nil];
[restaurants sortUsingDescriptors:sortDescriptors];
[hotels sortUsingDescriptors:sortDescriptors];
[self setArrayOfRestaurants:restaurants];
[restaurants release];
[nameDescriptor release];
[sortDescriptors release];
[tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)atableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil ) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier]autorelease];
}
//set up cell
NSLog(#"For Restaurants List");
Restaurants *restaurants = [arrayOfRestaurants objectAtIndex:indexPath.row];
cell.textLabel.text = restaurants.Name;
return cell;
}
cityTorestaurants and restaurantTocity is relationship in core data..
Help Please..
In your RestaurantViewController create a property Restaurant* currentRestaurant
in your didSelectRowAtIndexPath:of the CityViewController set the property with self.restaurantVC.currentRestaurant = [arrayOfRestaurants objectAtIndex:indexPath.row];
This is kinda confusing so please bear with me.
I have an array (listOfStates) of dictionaries. Where listOfStates has this structure:
{stateName} - {stateCapital}
{Alabama} - {Montgomery}
{Alaska} - {Juneau}
{Arizona} - {Phoenix}
...
{West Virginia} - {Charleston}
{Wisconsin} - {Madison}
{Wyoming} - {Cheyenne}
This is the code used to obtain the 1st letter of each US State(stateName) in order to group them together alphabetically:
listOfStates = [[NSArray alloc] init];
stateIndex = [[NSMutableArray alloc] init];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (NSDictionary *row in listOfStates) {
[tempArray addObject:[row valueForKey:#"stateName"]];
for (int i=0; i<[tempArray count]-1; i++){
char alphabet = [[tempArray objectAtIndex:i] characterAtIndex:0];
NSString *uniChar = [NSString stringWithFormat:#"%C", alphabet];
if (![stateIndex containsObject:uniChar]){
[stateIndex addObject:uniChar];
}
}
}
That code works beautifully, however I'm having issues understanding how to populate a tableview cell with BOTH the #"stateName" and #"stateCapital"(as the subtitle) after I use NSPredicate to sort the array.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
//---get the letter in the current section---
NSString *alphabet = [stateIndex objectAtIndex:[indexPath section]];
//---get all states beginning with the letter---
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *states = [[listOfStates valueForKey:#"stateName"] filteredArrayUsingPredicate:predicate];
//---extract the relevant state from the states object---
cell.textLabel.text = [states objectAtIndex:indexPath.row];
//cell.textLabel.text = [[listOfStates objectAtIndex:indexPath.row] objectForKey:#"stateName"];
//cell.detailTextLabel.text = [[listOfStates objectAtIndex:indexPath.row] objectForKey:#"stateCapital"];
return cell;
}
Any help is appreciated and I am more than willing to send the entire project, if you think it'll help you understand.
Thank you so much.
cell.textLabel.text = [[states objectAtIndex:indexPath.row] objectForKey:#"stateName"];
cell.detailTextLabel.text =[states objectAtIndex:indexPath.row] objectForKey:#"stateCapital"];
Update:
Unfortunately, the 'states' array only
includes the state names...
Change the predicate and filter to:
NSPredicate *p=[NSPredicate predicateWithFormat:#"stateName beginswith[c] %#", alphabet];
NSArray *states=[listOfStates filteredArrayUsingPredicate:p];
...that will give you an array of states that all start with the same letter. Then you can sort the array and the row will give you the right state dictionary.
Maybe change the data structure so you have one dictionary with state name as a key and state capital as a value. That way you can sort your keys and get the value using the keys, not indexes.
I use coredata to fill an array with data that is displayed in a tableview.
In the tableview, I have two section.
When a cell is pushed in section1, I want that cell to be moved to section2, and the other way around.
Im not quite sure how to accomplish this, and I been sitting trying to figure it out for about 8 hours now.
This is what I got so far:
I use this code to get the data:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"creationDate" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:&sortDescriptor count:1];
NSMutableArray *sortedIngredients = [[NSMutableArray alloc] initWithArray:[event.tags allObjects]];
[sortedIngredients sortUsingDescriptors:sortDescriptors];
self.tagsArray = sortedIngredients;
[sortDescriptor release];
[sortDescriptors release];
[sortedIngredients release];
In didSelectRowForIndexPath, I figure out how to remove the cell:
Tag *tag = [tagsArray objectAtIndex:indexPath.row];
NSManagedObjectContext *context = event.managedObjectContext;
[context deleteObject:tag];
[tagsArray removeObject:tag];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
How do I insert this cell in section 2 in the tableView?
Should I create 2 arrays?
I tried some code that used NSDictiorary, like this:
[tableView addObject: sectionOneObject forKey:#"Section1"];
[tableView addObject: sectionTwoObjects forKey: #"Section2"];
But I never manage to get it to work.
Any help would be highly appreciated!
Thanks in advance
Check out -insertRowsAtIndexPaths:withRowAnimation, e.g.:
unsigned _insertionIndices[2] = {1,0}; // second section, first row
NSIndexPath *_insertionIndexPath = [[NSIndexPath alloc] initWithIndexes: _insertionIndices length:2];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:_insertionIndexPath] withRowAnimation: UITableViewRowAnimationRight];
[_insertionIndexPath release];