Ios 在UtableView滚动时,在MKMapView上放置图钉,从特定屏幕位置的单元格获取坐标。“做别针”;舞蹈;
我正在尝试的内容的背景和摘要:Ios 在UtableView滚动时,在MKMapView上放置图钉,从特定屏幕位置的单元格获取坐标。“做别针”;舞蹈;,ios,objective-c,multithreading,uitableview,uiscrollview,Ios,Objective C,Multithreading,Uitableview,Uiscrollview,我正在尝试的内容的背景和摘要: 我有一个UIViewController,其中包含一个MKMapView和一个子UITableView 表视图中的每个单元格都包含一组坐标 我想要一个大头针落在地图上顶部单元格中包含的坐标处 我希望在表格视图滚动时,引脚“实时”下降。当一个单元格到达某个y轴屏幕位置时,一个管脚会落在其贴图坐标处,当它离开该y轴位置时,该管脚会消失,并在下一个单元格的贴图坐标处被一个新管脚替换 理想的效果是,当表格视图滚动时,图钉在地图上的不同位置快速消失和重新出现(一次一个)。
- 我有一个UIViewController,其中包含一个MKMapView和一个子UITableView
- 表视图中的每个单元格都包含一组坐标
- 我想要一个大头针落在地图上顶部单元格中包含的坐标处
- 我希望在表格视图滚动时,引脚“实时”下降。当一个单元格到达某个y轴屏幕位置时,一个管脚会落在其贴图坐标处,当它离开该y轴位置时,该管脚会消失,并在下一个单元格的贴图坐标处被一个新管脚替换
- 理想的效果是,当表格视图滚动时,图钉在地图上的不同位置快速消失和重新出现(一次一个)。我称之为“跳舞”
- 我不希望在y位置选择单元格,因为我需要使用didSelectRow方法推送到新的视图控制器
scrollViewDidScroll
方法来解决这个问题,当表视图滚动时,该方法会被反复调用。我对它进行了设置,这样每次调用它时,它都会获得表视图顶部单元格的索引路径,如果此索引路径与上次调用该方法时不同(意味着新单元格已到达顶部),则会调用自定义方法newPinFromScrolling
。此方法应移除最后一个顶部单元格中的pin,并将新pin放置在地图上新顶部单元格中指定的坐标处
我认为上面提到的两种方法对任何试图弄明白这一点的人来说都是最相关的。我的ViewDidLoad
主要是基础工作,但我还是试着加入一些解释性的注释
我的ViewController中没有任何内容。h
ViewController.m
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import "AnnotationClass.h"
@interface ViewController () <UITableViewDelegate,UITableViewDataSource,MKMapViewDelegate>
@end
@implementation ViewController
{
UITableView * myTableView;
NSMutableArray * coordinatesArray;
MKMapView * mapView;
CLLocationCoordinate2D centerLocation;
NSIndexPath * topRowIndexPath;
NSIndexPath * oldRowIndexPath;
UILabel * indexPathLabel;
UIView * labelContainerView;
}
- (void)viewDidLoad {
[super viewDidLoad];
//basic positioning stuff
labelContainerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 50)];
labelContainerView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:labelContainerView];
indexPathLabel = [[UILabel alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/2, 20, 50, 30)];
indexPathLabel.text = @"0";
[labelContainerView addSubview:indexPathLabel];
myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0,(([UIScreen mainScreen].bounds.size.height - 50)/2) + 50, [UIScreen mainScreen].bounds.size.width, ([UIScreen mainScreen].bounds.size.height - 50)/2) style:UITableViewStylePlain];
[myTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
myTableView.dataSource = self;
myTableView.delegate = self;
[self.view addSubview:myTableView];
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 50, [UIScreen mainScreen].bounds.size.width, ([UIScreen mainScreen].bounds.size.height - 50)/2)];
mapView.delegate = self;
[self.view addSubview:mapView];
coordinatesArray = [@[] mutableCopy];
//random location to drop pins around
centerLocation = CLLocationCoordinate2DMake(37.72012665, -101.59623681);
//way of getting 25 random locations around the center location
for(int i=0;i<25;i++) {
CGFloat latDelta = rand()* .99/RAND_MAX - 0.02;
CGFloat lonDelta = rand()* .99/RAND_MAX - 0.08;
CLLocationCoordinate2D cellCoordinate = {centerLocation.latitude+latDelta, centerLocation.longitude+lonDelta};
//adding these coordinates to the table view array
[coordinatesArray addObject:[NSValue valueWithMKCoordinate:cellCoordinate]];
}
//dropping all the pins on the map before any scrolling happens
for ( int i=0; i<[coordinatesArray count]; i++)
{
CLLocationCoordinate2D annotationCoordinates = [[coordinatesArray objectAtIndex:i] MKCoordinateValue];
AnnotationClass * dropPin = [[AnnotationClass alloc] init];
dropPin.coordinate = annotationCoordinates;
[mapView addAnnotation:dropPin];
}
//set our viewing region
MKCoordinateRegion region = MKCoordinateRegionMake(centerLocation, MKCoordinateSpanMake(2.5, 2.5));
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:NO];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return coordinatesArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = [myTableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
CLLocationCoordinate2D cellCoordinate = [[coordinatesArray objectAtIndex:indexPath.row] MKCoordinateValue];
cell.textLabel.text = [NSString stringWithFormat:@"%f, %f", cellCoordinate.latitude, cellCoordinate.longitude];
return cell;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGPoint offset = myTableView.contentOffset;
//the line below gets the index path of the cell located at the y coordinate of the table view's origin (the cell touching the top)
topRowIndexPath = [myTableView indexPathForRowAtPoint:offset];
//offset.y > 0 because indexpath = null when offset is less than 0
if (topRowIndexPath != oldRowIndexPath && offset.y > 0) {
//this method gets called every time the index path changes
[self newPinFromScrolling];
//this label gets updated in real time
indexPathLabel.text = [NSString stringWithFormat:@"%lu",topRowIndexPath.row];
}
//oldRowIndexPath gets compared to topRowIndexpath next time this method is called
oldRowIndexPath = topRowIndexPath;
}
- (void)newPinFromScrolling {
//remove previous pins. This seems to happen "in real time" too.
[mapView removeAnnotations:mapView.annotations];
//below is all the code needed to drop a new pin on the map at the coordinates specified in the topmost cell. Some or all of it does not get called during the scroll event.
CLLocationCoordinate2D newPinCoordinates = [[coordinatesArray objectAtIndex:topRowIndexPath.row] MKCoordinateValue];
AnnotationClass * newPin = [[AnnotationClass alloc] init];
newPin.coordinate = newPinCoordinates;
//An NSLog of newPin.coordinate shows that the pin coordinates get updated in real time.
//It seems that this line here is the one that does not get called until the table view stops.
[mapView addAnnotation:newPin];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
#import "AnnotationClass.h"
@implementation AnnotationClass
-(void)setCoordinate:(CLLocationCoordinate2D)newCoordinate
{
_coordinate = newCoordinate;
}
@end
结果:
- 当表格视图滚动时,
确实会被称为“实时”newPinFromScrolling
- 但是,当表格视图滚动时,新的管脚不会实时下降。只有当表视图完全停止时,它们才会下降
- 我制作了一个标签,每次顶部单元格的索引路径发生变化时都会实时更新,所以我猜手机在表视图滚动时是否能够实时更新取决于任务的复杂性
如果是这种情况,有没有办法强迫手机尝试使用
newPinFromScrolling
方法完成任务?它们是否可以在单独的线程中完成,并在表视图滚动过快时取消没有时间完成的线程?如果已经安排好了,那么我将开始研究降低表格视图滚动速度的方法,这样“舞蹈”就不会中断。结果表明,更改插针位置所需做的只是更改其坐标(只需确保已将其添加到地图中)。每次索引路径更改时添加和删除它都是不必要的。除了主线程之外,您将无法从任何线程更新UI。嘿,谢谢,这在其他方面帮了我的忙。有件事要做。还在想这件事我是偶然发现的。事实证明,要在屏幕上改变位置,只需改变引脚坐标即可。太棒了!做得好。回答你自己的问题;)
#import "AnnotationClass.h"
@implementation AnnotationClass
-(void)setCoordinate:(CLLocationCoordinate2D)newCoordinate
{
_coordinate = newCoordinate;
}
@end