按计算距离对 UITableView 单元格进行排序(解析)
Order UITableView cells by calculated distance (Parse)
我在解析时创建的数据库有问题。我有一个 table 显示了各个本地有多少英里(一旦您从 DB 下载列表)问题是我会按向上的距离订购它,但我不知道该怎么做。我用来计算距离的代码是这样的:
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = @"Ristoranti";
// The key of the PFObject to display in the label of the default cell style
self.textKey = @"NomeLocale";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
// The number of objects to show per page
self.objectsPerPage = 100;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
if(IS_OS_8_OR_LATER) {
[locationManager requestWhenInUseAuthorization];
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(refreshTable:)
name:@"refreshTable"
object:nil];
}
- (void)refreshTable:(NSNotification *) notification
{
// Reload the recipes
[self loadObjects];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"refreshTable" object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
query.limit = 100;
[query orderByAscending:@"createdAt"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = @"RecipeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
NSString *AntDef = [NSString stringWithFormat:@"%@", [object objectForKey:@"AnteprimaDefault"]];
if ([AntDef isEqualToString:@"Null"])
{
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:@"ImageDefault.png"];
thumbnailImageView.layer.cornerRadius = thumbnailImageView.frame.size.width / 2;
thumbnailImageView.clipsToBounds = YES;
thumbnailImageView.layer.borderWidth = 0.5;
thumbnailImageView.layer.borderColor = [UIColor lightGrayColor].CGColor;
}
else
{
PFFile *thumbnail = [object objectForKey:@"Anteprima1"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:@"placeholder.jpg"];
thumbnailImageView.file = thumbnail;
thumbnailImageView.layer.cornerRadius = thumbnailImageView.frame.size.width / 2;
thumbnailImageView.clipsToBounds = YES;
[thumbnailImageView loadInBackground];
}
Lat = [[object objectForKey:@"Latitudine"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
Long = [[object objectForKey:@"Longitudine"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
Latdouble = [Lat doubleValue];
Longdouble = [Long doubleValue];
NSArray *locations = [NSArray arrayWithObjects:[[CLLocation alloc] initWithLatitude:Latdouble longitude:Longdouble], nil];
//NSLog(@"LOCATIONS COORDINATE: %@", locations);
CLLocation *currentLocation = [[CLLocation alloc] initWithLatitude:locationManager.location.coordinate.latitude longitude:locationManager.location.coordinate.longitude];;
CLLocation *nearestLoc = nil;
CLLocationDistance nearestDis = FLT_MAX;
for (CLLocation *location in locations) {
CLLocationDistance distance = [currentLocation distanceFromLocation:location];
for (CLLocation *location in locations) {
distance = [currentLocation distanceFromLocation:location];
if (nearestDis > distance) {
nearestLoc = location;
nearestDis = distance;
}
}
text12 = [NSString stringWithFormat:@"%.1f Km", nearestDis/1000];
}
...
}
提前致谢:)
假设您来自 Parse.com
的响应数据是 NSArray
。
我建议:
- 执行请求。
- 排序
NSArray
- 重新加载数据。
可以使用以下块对数组进行排序:sortedArrayUsingComparator:^NSComparisonResult(id a, id b)
NSArray *sortedArray;
sortedArray = [initialDataArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
//Here do the method to compare if `a` is closer or `b` is closer
YourParseObject *aObject = (YourParseObject *)a;
YourParseObject *bObject = (YourParseObject *)b;
//Get Latitude & Longitude from a and b.
//return NSOrderedAscending or NSOrderedDescending according to which one of a or b is the closest, using your previous method I suppose to be working.
}];
所以 sortedArray
看起来像这样:
{
YourParseObject the closest one
YourParseObject the second closest one
//...
YourParseObject the farthest one.
}
一旦完成:
[yourTableView reloadData]
我今天刚遇到这个问题,发现Parse.com已经实现了这个解决方案:
如果您正在使用 Parse 的 PFQueryTableViewController.h
,您需要将其添加到您的 queryForTable
方法中:
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query whereKey:@"yourClassPFLocationField" nearGeoPoint:yourLocation];
return query;
}
如果您不使用 PFQueryTable
,同样适用,只需在加载查询时使用该排序方法即可。
一切都在 PFQuery
文档中 :D
我在解析时创建的数据库有问题。我有一个 table 显示了各个本地有多少英里(一旦您从 DB 下载列表)问题是我会按向上的距离订购它,但我不知道该怎么做。我用来计算距离的代码是这样的:
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = @"Ristoranti";
// The key of the PFObject to display in the label of the default cell style
self.textKey = @"NomeLocale";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
// The number of objects to show per page
self.objectsPerPage = 100;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
if(IS_OS_8_OR_LATER) {
[locationManager requestWhenInUseAuthorization];
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(refreshTable:)
name:@"refreshTable"
object:nil];
}
- (void)refreshTable:(NSNotification *) notification
{
// Reload the recipes
[self loadObjects];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"refreshTable" object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
query.limit = 100;
[query orderByAscending:@"createdAt"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = @"RecipeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
NSString *AntDef = [NSString stringWithFormat:@"%@", [object objectForKey:@"AnteprimaDefault"]];
if ([AntDef isEqualToString:@"Null"])
{
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:@"ImageDefault.png"];
thumbnailImageView.layer.cornerRadius = thumbnailImageView.frame.size.width / 2;
thumbnailImageView.clipsToBounds = YES;
thumbnailImageView.layer.borderWidth = 0.5;
thumbnailImageView.layer.borderColor = [UIColor lightGrayColor].CGColor;
}
else
{
PFFile *thumbnail = [object objectForKey:@"Anteprima1"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:@"placeholder.jpg"];
thumbnailImageView.file = thumbnail;
thumbnailImageView.layer.cornerRadius = thumbnailImageView.frame.size.width / 2;
thumbnailImageView.clipsToBounds = YES;
[thumbnailImageView loadInBackground];
}
Lat = [[object objectForKey:@"Latitudine"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
Long = [[object objectForKey:@"Longitudine"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
Latdouble = [Lat doubleValue];
Longdouble = [Long doubleValue];
NSArray *locations = [NSArray arrayWithObjects:[[CLLocation alloc] initWithLatitude:Latdouble longitude:Longdouble], nil];
//NSLog(@"LOCATIONS COORDINATE: %@", locations);
CLLocation *currentLocation = [[CLLocation alloc] initWithLatitude:locationManager.location.coordinate.latitude longitude:locationManager.location.coordinate.longitude];;
CLLocation *nearestLoc = nil;
CLLocationDistance nearestDis = FLT_MAX;
for (CLLocation *location in locations) {
CLLocationDistance distance = [currentLocation distanceFromLocation:location];
for (CLLocation *location in locations) {
distance = [currentLocation distanceFromLocation:location];
if (nearestDis > distance) {
nearestLoc = location;
nearestDis = distance;
}
}
text12 = [NSString stringWithFormat:@"%.1f Km", nearestDis/1000];
}
...
}
提前致谢:)
假设您来自 Parse.com
的响应数据是 NSArray
。
我建议:
- 执行请求。
- 排序
NSArray
- 重新加载数据。
可以使用以下块对数组进行排序:sortedArrayUsingComparator:^NSComparisonResult(id a, id b)
NSArray *sortedArray;
sortedArray = [initialDataArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
//Here do the method to compare if `a` is closer or `b` is closer
YourParseObject *aObject = (YourParseObject *)a;
YourParseObject *bObject = (YourParseObject *)b;
//Get Latitude & Longitude from a and b.
//return NSOrderedAscending or NSOrderedDescending according to which one of a or b is the closest, using your previous method I suppose to be working.
}];
所以 sortedArray
看起来像这样:
{
YourParseObject the closest one
YourParseObject the second closest one
//...
YourParseObject the farthest one.
}
一旦完成:
[yourTableView reloadData]
我今天刚遇到这个问题,发现Parse.com已经实现了这个解决方案:
如果您正在使用 Parse 的 PFQueryTableViewController.h
,您需要将其添加到您的 queryForTable
方法中:
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query whereKey:@"yourClassPFLocationField" nearGeoPoint:yourLocation];
return query;
}
如果您不使用 PFQueryTable
,同样适用,只需在加载查询时使用该排序方法即可。
一切都在 PFQuery
文档中 :D