我有一个包含Lat和Long信息的SQL DB。我找到了我当前的位置,并且能够从当前位置获取每个位置的距离。我可以让我的tableview显示这个距离,但是知道我想对那个tableview进行排序,以便最先列出最近的。
我的想法是我需要添加到我的SQL DB数据的距离,对某些方法进行排序,然后将该信息显示回tableview。
我的想法是我会在TableView中完成所有这些操作。寻找有关如何执行此操作的指导,以及我是否应该在tableview中执行此操作。
#import "TulsaMasterViewController.h"
#import "TulsaDetailViewController.h"
#import "Bars.h"
#import "BarDatabase.h"
@implementation TulsaMasterViewController
@synthesize barArray = _barArray;
@synthesize currentLat = _currentLat;
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
currentLat = newLocation;
if (newLocation.horizontalAccuracy <= 100.0f) {
[lm stopUpdatingLocation];
}
[self.tableView reloadData];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSString *msg = [[NSString alloc]initWithString:@"Error obtaining location"];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error" message:msg delegate:nil cancelButtonTitle:@"Done" otherButtonTitles:nil];
[alert show];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.barArray count];
}
- (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];
}
//Get the object from the array.
Bars *barObj = [self.barInfo objectAtIndex:indexPath.row];
//Set the name.
cell.textLabel.text = barObj.barName;
if (currentLat == nil) {
cell.detailTextLabel.text = [NSString stringWithFormat:@"?"];
}else
{
cell.detailTextLabel.text = [NSString stringWithFormat:@"%.02f", cachedDist];
}
// Set up the cell
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"ShowDetails"]) {
TulsaDetailViewController *detailViewController = [segue destinationViewController];
detailViewController.detailItem = [self.barArray objectAtIndex:[self.tableView indexPathForSelectedRow].row];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.barArray = [BarDatabase database].barInfo;
lm = [[CLLocationManager alloc] init];
lm.delegate = self;
[lm startUpdatingLocation];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
for (Bars *barObj in barArray) {
NSString *strLat = barObj.Lat;
NSString *strLong = barObj.Long;
CLLocation *barLocation = [[CLLocation alloc] initWithLatitude:[strLat doubleValue] longitude:[strLong doubleValue]];
CLLocationDistance distance = [currentLat distanceFromLocation:barLocation]/1000;
[barArray addObject:[NSNumber numberWithDouble:distance]];
NSSortDescriptor *sort=[NSSortDescriptor sortDescriptorWithKey:@"cachedDist" ascending:YES];
[barArray sortUsingDescriptors:[NSArray arrayWithObject:sort]];
}
参考我的其余代码
Bars.h
#import <Foundation/Foundation.h>
@interface Bars : NSObject {
NSString *barName;
NSString *barAddress;
NSString *Lat;
NSString *Long;
NSString *cachedDist;
}
@property (nonatomic, copy) NSString *barName;
@property (nonatomic, copy) NSString *barAddress;
@property (nonatomic, copy) NSString *Lat;
@property (nonatomic, copy) NSString *Long;
@property (nonatomic, copy) NSString *cachedDist;
- (id)initWithName:(NSString *)name address:(NSString *)address latitude:(NSString *)latitude longitude:(NSString *)longitude distance:(NSString *)distance;
@end
Bars.m
#import "Bars.h"
@implementation Bars
@synthesize barName = _barName;
@synthesize barAddress = _barAddress;
@synthesize Lat = _Lat;
@synthesize Long = _Long;
@synthesize cachedDist = _cachedDist;
- (id)initWithName:(NSString *)name address:(NSString *)address latitude:(NSString *)latitude longitude:(NSString *)longitude distance:(NSString *)distance;
{
if ((self = [super init])) {
self.barName = name;
self.barAddress = address;
self.Lat = latitude;
self.Long = longitude;
self.cachedDist = distance;
}
return self;
}
@end
BarDatabase.h
#import <Foundation/Foundation.h>
#import <sqlite3.h>
@interface BarDatabase : NSObject
{
sqlite3 *_database;
}
+ (BarDatabase *)database;
- (NSMutableArray *)barInfo;
@end
BarDatabase.m
#import "BarDatabase.h"
#import "Bars.h"
@implementation BarDatabase
static BarDatabase *_database;
+ (BarDatabase *)database {
if (_database == nil) {
_database = [[BarDatabase alloc] init];
}
return _database;
}
- (id)init {
if ((self = [super init])) {
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:@"TulsaBars"
ofType:@"sqlite"];
if (sqlite3_open([sqLiteDb UTF8String], &_database) != SQLITE_OK) {
NSLog(@"Failed to open database!");
}
}
return self;
}
- (void)dealloc {
sqlite3_close(_database);
}
- (NSMutableArray *)barInfo {
NSMutableArray *retval = [[NSMutableArray alloc] init];
NSString *query = @"SELECT * FROM TulsaBars";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
char *nameChars = (char *) sqlite3_column_text(statement, 1);
char *addressChars = (char *) sqlite3_column_text(statement, 2);
char *latChars = (char *) sqlite3_column_text(statement, 8);
char *longChars = (char *) sqlite3_column_text(statement, 9);
NSString *name = [[NSString alloc] initWithUTF8String:nameChars];
NSString *address = [[NSString alloc] initWithUTF8String:addressChars];
NSString *latitude = [[NSString alloc] initWithUTF8String:latChars];
NSString *longitude = [[NSString alloc] initWithUTF8String:longChars];
Bars *info = [[Bars alloc]
initWithName:name address:address latitude:latitude longitude:longitude];
[retval addObject:info];
}
sqlite3_finalize(statement);
}
return retval;
}
@end
答案 0 :(得分:0)
槽糕。在cellForRowAtIndexPath中不应该发生排序。这在游戏中为时已晚。如果每个单元格都是1 bar,并且条形应按距离排序,我建议您在self.barInfo的懒惰getter中进行排序(如果这是你的条形列表)。
我不确定你的模型是什么样的,但是如果每个bar对象都有一个与你的参考点无关的属性,那么你的排序看起来就像你在那里那样。
这种排序只会在加载第一个单元格(即“懒惰”部分)然后进行缓存时发生。所以你的cellForRowAtIndexPath:只需要在它的indexPath行上询问模型对象,相信它的顺序是正确的。
我不确定你熟悉这个术语有多少,所以请随意提出澄清问题,我会重复答案。
分享更多代码后编辑:
我想你应该添加一个@property到名为像cachedDistance酒吧,每当你来到屏幕(viewWillAppear中),遍历酒吧并设置其缓存的距离(使用类似的代码,你有什么cellForRow ...)。然后为self.barArray实现一个getter:-(NSArray *)barArray
实际上返回barArray,它使用sortDescriptor排序,并将缓存的distance属性的名称作为键。这将简化你的cellForRow ...代码。
然后,您可以扩展逻辑,以便在获得位置更新时重新计算距离,可能仅在距离之前有一定距离时才会重新计算距离。