gpt4 book ai didi

ios - NSMutableArray 数据按距离排序

转载 作者:行者123 更新时间:2023-11-29 03:04:52 25 4
gpt4 key购买 nike

我的 MutableArray 有问题。我的 TableView 中有数据数组,一切正常,但是当数据按距离排序并且我在单元格中选择一个项目时,它会在新的 View Controller 中显示不正确的数据。它显示没有排序的数据。这就像一个断开的链接)希望得到你的帮助)

我是 obj-c 的新手,所以我很抱歉)

这是我的代码:

       list = [[NSMutableArray alloc] init];

[list addObject:@{@"name": @"Central office", @"address":@"наб. Обводного канала, д.66А", @"phone":@"+7 (812) 320-56-21 (многоканальный)", @"workTime":@"ПН-ПТ: с 9:30 до 18:30", @"email":@"mail@ibins.ru", @"payment":@"Принимаются к оплате пластиковые карты VISA и MasterCard", @"longitude":@30.336842, @"latitude":@59.913950}];

[list addObject:@{@"name": @"Second office", @"address":@"ул. Камышовая, д.38", @"phone":@"+7 (812) 992-992-6; +7 (812) 456-26-43", @"workTime":@"Ежедневно: с 9:30 до 20:00", @"email":@"sever@ibins.ru", @"payment":@"Принимаются к оплате пластиковые карты VISA и MasterCard", @"longitude":@30.219863, @"latitude":@60.008805}];

[list addObject:@{@"name": @"Third office", @"address":@"Street name", @"phone":@"phone number", @"workTime":@"Work time", @"email":@"email address", @"longitude":@30.294254, @"latitude":@60.028728}];

[self constructList];
[self constructPins];
}



- (IBAction)switchDisplayType:(id)sender {
[UIView beginAnimations:@"View Flip" context:nil];
[UIView setAnimationDuration:0.80];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
[UIView commitAnimations];

if ([(UISegmentedControl*)sender selectedSegmentIndex] == 1) {
map.hidden = YES;
contentSV.hidden = NO;
}
else {
map.hidden = NO;
contentSV.hidden = YES;
}
}

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString* BridgeAnnotationIdentifier = @"bridgeAnnotationIdentifier";

MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:BridgeAnnotationIdentifier] autorelease];
customPinView.pinColor = MKPinAnnotationColorRed;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;

UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
// NSLog(@"%@",rightButton);
[rightButton addTarget:self
action:@selector(annotationButtonTapped:)
forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;//[kml viewForAnnotation:annotation];
}

- (void)annotationButtonTapped:(id)sender {
DetailVC *sampleVC = [[DetailVC alloc] initWithNibName:@"DetailVC" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:sampleVC animated:YES];
[sampleVC release];

for (NSDictionary *dict in list) {
if ([[dict valueForKey:@"name"] isEqualToString:selectedAnnTitle]) {
[sampleVC updateViewWithDict:dict];
}
}
}



- (void)constructPins {
for (NSDictionary *dict in list) {
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.3;
span.longitudeDelta = 0.3;

CLLocationCoordinate2D location;

location.latitude = [[dict valueForKey:@"latitude"] floatValue];
location.longitude = [[dict valueForKey:@"longitude"] floatValue];

if (location.latitude == 0.0 && location.longitude == 0.0)
return;

region.span = span;
region.center = location;

MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = location;
point.title = [dict valueForKey:@"name"];

[map addAnnotation:point];
[map setRegion:region animated:YES];
}
}

- (void)constructList {
int n = 0;
for (NSDictionary *dict in list) {
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 100*n, 320, 100)];
container.backgroundColor = [UIColor whiteColor];

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
button.tag = n;
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
[container addSubview:button];


NSString *str = [NSString stringWithFormat:@"%@\nAddress: %@\nPhone: %@\nWork Time: %@", [dict valueForKey:@"name"], [dict valueForKey:@"address"], [dict valueForKey:@"phone"], [dict valueForKey:@"workTime"]];
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 300, 80)];
nameLabel.textAlignment = NSTextAlignmentLeft;
nameLabel.numberOfLines = 0;
nameLabel.text = str;
nameLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:12.0];
[container addSubview:nameLabel];


UIView *separator = [[UIView alloc]initWithFrame:CGRectMake(0, 99, 320, 1)];
separator.backgroundColor = [UIColor darkGrayColor];
[container addSubview:separator];


[contentSV addSubview:container];


n++;
contentSV.contentSize = CGSizeMake(0, 100*n);
}
}

- (float)distanceBetweenLat1:(float)tlat1 lon1:(float)tlon1 lat2:(float)tlat2 lon2:(float)tlon2 {
float result = 0.0;
int R = 6371;

float currentLatitude = tlat1;
float currentLongtitude = tlon1;

float lat2 = tlat2;
float lon2 = tlon2;

float dLat = (lat2-currentLatitude)*M_PI/180;
float dLon = (lon2-currentLongtitude)*M_PI/180;
float nlLat = currentLatitude*M_PI/180;
lat2 = lat2*M_PI/180;

float a = sin(dLat/2) * sin(dLat/2) + sin(dLon/2) * sin(dLon/2) * cos(nlLat) * cos(lat2);
float c = 2 * atan2(sqrt(a), sqrt(1-a));
result = R * c;

return result;
}

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
selectedAnnTitle = [view.annotation title];

return;

DetailVC *sampleVC = [[DetailVC alloc] initWithNibName:@"DetailVC" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:sampleVC animated:YES];


NSString *ttl = [view.annotation title];

for (NSDictionary *dict in list) {
if ([[dict valueForKey:@"name"] isEqualToString:ttl]) {
[sampleVC updateViewWithDict:dict];
}
}

[map deselectAnnotation:view.annotation animated:NO];
}

- (void)buttonTapped:(id)sender {
DetailVC *sampleVC = [[DetailVC alloc] initWithNibName:@"DetailVC" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:sampleVC animated:YES];


int n = 0;
for (NSDictionary *dict in list) {
if (n == [sender tag]) {
[sampleVC updateViewWithDict:dict];
}
n++;
}
}

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
NSLog(@"didUpdateUserLocation");

MKAnnotationView* annotationView = [mapView viewForAnnotation:userLocation];
annotationView.canShowCallout = NO;

if (!userLocationUpdated) {
if (userLocation.coordinate.latitude > 0.1 && userLocation.coordinate.longitude > 0.1) {
// NSLog(@"SORT BY DISTANCE");

userLocationUpdated = YES;

for (int i = 0; i < [list count]; i++) {
NSMutableDictionary *record = [[NSMutableDictionary alloc] initWithDictionary:[list objectAtIndex:i]];

float latitude = [[record valueForKey:@"latitude"] floatValue];
float longitude = [[record valueForKey:@"longitude"] floatValue];

float dist = [self distanceBetweenLat1:map.userLocation.coordinate.latitude lon1:map.userLocation.coordinate.longitude lat2:latitude lon2:longitude];
NSNumber *distN = [NSNumber numberWithFloat:dist];
[record setObject:distN forKey:@"distance"];

[list replaceObjectAtIndex:i withObject:record];
}

NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"distance" ascending:YES];
NSArray *itemsListSorted = [[NSArray alloc] initWithArray:list];
itemsListSorted = [itemsListSorted sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];

for (UIView *view in contentSV.subviews) {
[view removeFromSuperview];
}

for (int i = 0; i < [itemsListSorted count]; i++) {
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 100*i, 320, 100)];
container.backgroundColor = [UIColor whiteColor];

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
button.tag = i;
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
[container addSubview:button];


NSString *str = [NSString stringWithFormat:@"%@\nAddress: %@\nPhone: %@\nWorkTime: %@", [[itemsListSorted objectAtIndex:i] valueForKey:@"name"], [[itemsListSorted objectAtIndex:i] valueForKey:@"address"], [[itemsListSorted objectAtIndex:i] valueForKey:@"phone"], [[itemsListSorted objectAtIndex:i] valueForKey:@"workTime"]];
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 300, 80)];
nameLabel.textAlignment = NSTextAlignmentLeft;
nameLabel.numberOfLines = 0;
nameLabel.text = str;
nameLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:12.0];
[container addSubview:nameLabel];


UILabel *distanceLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 2, 300, 21)];
distanceLabel.textAlignment = NSTextAlignmentRight;
distanceLabel.text = [NSString stringWithFormat:@"%.1f км", [[[itemsListSorted objectAtIndex:i] valueForKey:@"distance"] floatValue]];
distanceLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:12.0];
distanceLabel.textColor = [UIColor lightGrayColor];
[container addSubview:distanceLabel];


UIView *separator = [[UIView alloc]initWithFrame:CGRectMake(0, 99, 320, 1)];
separator.backgroundColor = [UIColor darkGrayColor];
[container addSubview:separator];


[contentSV addSubview:container];


contentSV.contentSize = CGSizeMake(0, 100*(i+1));
}
}
}
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}

@end

最佳答案

虽然此代码存在许多问题(其中最少的是距离计算的一些小精度问题),问题不在于距离计算

详细 View Controller 显示不正确的数据,因为它从 list 数组中获得数据,该数组不是本身按距离排序。

didUpdateUserLocation 委托(delegate)方法中,list 的内容被复制到名为 itemsListSorted本地数组。

只有 itemsListSorted 数组按距离排序,然后使用此本地 数组更新显示。

但原始的 list 数组(buttonTapped 方法将其用作发送到详细 View Controller 的数据源)从不 已更新。

因此,如果“Central Office”位于 list 中的索引 0,但在 itemsListSorted 中移动到索引 2,则显示会显示正确的位置,但是当您点击它时,buttonTapped 方法从 list 数组发送索引 2 处的项目,该数组有“Central Office”(它仍然在索引 0 列表).


解决此问题的一种方法是停止使用本地数组并直接对 list 数组进行排序。

didUpdateUserLocation 中,您可以替换这两行:

NSArray *itemsListSorted = [[NSArray alloc] initWithArray:list];
itemsListSorted = [itemsListSorted sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];

用这个:

[list sortUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];

然后用 list 替换所有对 itemsListSorted 的引用。



关于代码的其他问题,没有足够的空间将它们全部指出或在一个答案中解释它们。然而,这里只是一些亮点:

  • 不要手动创建“表格 View ”,而是使用实际的 UITableView
  • 不要手动计算坐标之间的距离,而是使用 CLLocation 类中的 distanceFromLocation 方法 MKMetersBetweenMapPoints功能。
  • viewForAnnotation 中,如果 annotationMKUserLocation 类型,您应该返回 nil 否则它将显示为红色别针和其他别针一样。
  • 使用 ARC 而不是手动内存管理。

关于ios - NSMutableArray 数据按距离排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22901040/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com