如何将MapViewController设置为Datasource到TableViewController以显示单元格中的距离

时间:2013-01-25 02:25:02

标签: uitableview mkmapview distance

我的应用程序有一个tabbarcontroller,带有一个UIViewController(FirstViewController,调用它mapVC),带有mapview和一个UITableViewController(SecondViewController,称之为tableVC)。该应用程序从Web获取数据并将其放入CD-db,每个VC执行对数据库的提取。每个实体都被命名为Holiday(不要问),它有一个lat和long属性。

这是UITabBarController子类,它尝试将mapVC设置为tableVC的数据源:

- (void)viewDidLoad{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    FirstViewController *mapVC;
    SecondViewController *tableVC;

    for(UIViewController *anyVC in self.viewControllers)
    {
        if([anyVC.class isKindOfClass:[SecondViewController class]]){
            tableVC = (SecondViewController *)anyVC;
        } else if ([anyVC.class isKindOfClass:[FirstViewController class]]){
            mapVC = (FirstViewController *)anyVC;
        }
    }

    tableVC.tableView.dataSource = mapVC;
    tableVC.tableView.delegate = mapVC;
}

以下是mapVC的相关部分:

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "SecondViewController.h"

#define METERS_PER_MILE 2609.344

@interface FirstViewController : UIViewController <MKMapViewDelegate, UITableViewDataSource, UITableViewDelegate>{
    BOOL _doneInitialZoom;

}

@property (strong, nonatomic) IBOutlet MKMapView *_mapView;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *refreshButton;
@property (nonatomic, strong) NSString *entityName;
@property (strong, nonatomic) CLLocation *userLocation;

- (IBAction)refreshTapped:(id)sender;
-(void)showDetailView;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@end

及其实施:

#import "FirstViewController.h"
#import "Holiday.h"
#import "MyLocation.h"
#import "SDCoreDataController.h"
#import "MyTabBarController.h"
#import "TableViewCell.h"

- (void)loadRecordsFromCoreData {
    [self.managedObjectContext performBlockAndWait:^{
        [self.managedObjectContext reset];
        NSError *error = nil;
        NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:self.entityName];
        [request setSortDescriptors:[NSArray arrayWithObject:
                                     [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]]];
        self.farSiman = [self.managedObjectContext executeFetchRequest:request error:&error];

    }];
    NSLog(@"self.farSiman on launch = %@", self.farSiman);
}

- (void)plotStorePositions:(NSString *)responseString {

    for (id<MKAnnotation> annotation in _mapView.annotations) {
        [_mapView removeAnnotation:annotation];
    }

    NSLog(@"Dictionary is %@", self.farSiman);

    for (Holiday * holidayObject in self.farSiman) {

        NSString * latitude = holidayObject.latitude;
        NSString * longitude = holidayObject.longitude;
        NSString * storeDescription = holidayObject.name;
        NSString * address = holidayObject.address;


        CLLocationCoordinate2D coordinate;
        coordinate.latitude = latitude.doubleValue;
        coordinate.longitude = longitude.doubleValue;
        MyLocation *annotation = [[MyLocation alloc] initWithName:storeDescription address:address coordinate:coordinate distance:0];

        //
        CLLocation *pinLocation = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude];
        //[(MyLocation*)[view annotation] coordinate].latitude longitude:[(MyLocation*)[view annotation] coordinate].longitude]];

        self.userLocation = [[CLLocation alloc] initWithLatitude:self._mapView.userLocation.coordinate.latitude longitude:self._mapView.userLocation.coordinate.longitude];
        NSLog(@"PLOT>>userLocation is %@", userLocation);

        CLLocationDistance calculatedDistance = [pinLocation distanceFromLocation:self.userLocation];
        annotation.distance = calculatedDistance/1000;
        NSLog(@"PLOT>>Distance to pin %4.0f", annotation.distance);
        //

        [_mapView addAnnotation:annotation];

    }

}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [self.farSiman count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = nil;

    // Check to see whether the normal table or search results table is being displayed and set the Candy object from the appropriate array
    NSLog(@"Already in CFRAIP");

    static NSString *CellIdentifier = @"HolidayCell";
    if (cell == nil) {
        cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        //cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton;
    }
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    Holiday *holiday = [self.farSiman objectAtIndex:indexPath.row];
    cell.nameLabel.text = holiday.name;
    //cell.dateLabel.text = holiday.latitude;

    cell.dateLabel.text = [[self calculateDistanceForLat:[holiday.latitude doubleValue] Long:[holiday.longitude doubleValue]] stringValue];

    if (holiday.image != nil) {
        UIImage *image = [UIImage imageWithData:holiday.image];
        cell.imageView.image = image;
    } else {
        cell.imageView.image = nil;
    }
    return cell;
}

// Add new method above refreshTapped
- (NSNumber*)calculateDistanceForLat:(double)lati Long:(double)longi {
    double distancia;
    CLLocation *pinLocation = [[CLLocation alloc] initWithLatitude:lati longitude:longi];
    CLLocationDistance calculatedDistance = [pinLocation distanceFromLocation:self.userLocation];

    //test locations
    NSLog(@"pinLocations is %@, userLocation is %@", pinLocation, self.userLocation);

    distancia = calculatedDistance/1000;
    return [NSNumber numberWithDouble:distancia];
}

plotStoreLocations方法是mapVC工具栏中唯一一个来自UIButton的方法。

至于tableVC(SecondViewController)

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface SecondViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>

@property (nonatomic, strong) NSArray *dates;
@property (nonatomic, strong) NSString *entityName;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *refreshButton;

@property (strong,nonatomic) NSMutableArray *filteredResultsArray;
@property (strong,nonatomic) IBOutlet UISearchBar *resultsSearchBar;

@property (strong, nonatomic) CLLocation *userLocation;

- (IBAction)refreshButtonTouched:(id)sender;

及其实施:

- (void)loadRecordsFromCoreData {
    [self.managedObjectContext performBlockAndWait:^{
        [self.managedObjectContext reset];
        NSError *error = nil;
        NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:self.entityName];
        [request setSortDescriptors:[NSArray arrayWithObject:
                                     [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]]];
        self.dates = [self.managedObjectContext executeFetchRequest:request error:&error];
        NSLog(@"self.dates==%@",self.dates);
    }];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return [filteredResultsArray count];
    } else {
        return [self.dates count];
    }

    //return [self.dates count];
}

// Add new method above refreshTapped
- (NSNumber*)calculateDistanceForLat:(double)lati Long:(double)longi {
    double distancia;
    CLLocation *pinLocation = [[CLLocation alloc] initWithLatitude:lati longitude:longi];
    CLLocationDistance calculatedDistance = [pinLocation distanceFromLocation:self.userLocation];

    //test locations
    NSLog(@"pinLocations is %@, userLocation is %@", pinLocation, self.userLocation);

    distancia = calculatedDistance/1000;
    return [NSNumber numberWithDouble:distancia];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = nil;

    if (tableView == self.searchDisplayController.searchResultsTableView) {
        static NSString *CellIdentifier = @"HolidayCell";
        if (cell == nil) {
            cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        }
        cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        Holiday *holiday = [filteredResultsArray objectAtIndex:indexPath.row];
        NSLog(@"the holiday is %@", holiday.name);
        cell.nameLabel.text = holiday.name;

    } else {

        static NSString *CellIdentifier = @"HolidayCell";
        if (cell == nil) {
            cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        }
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        Holiday *holiday = [self.dates objectAtIndex:indexPath.row];
        cell.nameLabel.text = holiday.name;

        cell.dateLabel.text = [[self calculateDistanceForLat:[holiday.latitude doubleValue] Long:[holiday.longitude doubleValue]] stringValue];

        if (holiday.image != nil) {
            UIImage *image = [UIImage imageWithData:holiday.image];
            cell.imageView.image = image;
        } else {
            cell.imageView.image = nil;
        }
    }
    return cell;
}

最后MyLocation:

import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MyLocation : NSObject <MKAnnotation> {
    NSString *_name;
    NSString *_address;
    CLLocationCoordinate2D _coordinate;
}

@property (copy) NSString *name;
@property (copy) NSString *address;
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (assign) float distance;

- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate distance:(float)distance;

@end


#import "MyLocation.h"

@implementation MyLocation
@synthesize name = _name;
@synthesize address = _address;
@synthesize coordinate = _coordinate;
@synthesize distance = _distance;

- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate distance:(float)distance{
    if ((self = [super init])) {
        _name = [name copy];
        _address = [address copy];
        _coordinate = coordinate;
        _distance = distance;
    }
    return self;
}

- (NSString *)title {
    if ([_name isKindOfClass:[NSNull class]]) 
        return @"Unknown charge";
    else
        return _name;
}

- (NSString *)subtitle {
    return [NSString stringWithFormat:@"A %0.2f Kms", _distance];
    //return _address;
}

具体问题:

1)如果我在mapVC(新数据源)中添加了cFRAIP(noris&amp; nosit)方法,我是否需要从tableVC中删除它?

2)如果我从tableVC中删除cFRAIP和其他2(noris和nosit)方法,它会崩溃,因为没有数据源。所以tabbarcontroller对数据源的分配似乎并没有起作用。

3)最后如果我必须从tableVC中删除cFRAIP,我将失去UISearchBar tableview的能力。或者我错了吗?

当我运行应用程序时,mapVC是所选的vc。在webVC中调用plotStoreLocations的工具栏中的UIButton将显示为灰色,直到Web提取完成。此时,控制台会记录self.farsiman位置,这些位置是Holiday实体。我可以看到所有实体都登录到控制台。

当我单击绘图按钮时,将按照plotStorePositions中的指定正确记录userLocation,并且每个注释的距离值都是正确的。因此,正确计算每个MKAnnotation的距离。

当我切换到tableVC选项卡时,新的self.dates数组被记录在控制台中(因为我目前让tableVC进行另一次CD-db提取。我得到了每个引脚位置的信息:

  

已经在CFRAIP中的pinLocations是&lt; + 15.50288611,-88.02716389&gt; +/-   0.00m(速度-1.00 mps / course -1.00)@ 1/24 / 13,8:20:39 PM中央标准时间,userLocation为(null)

从CFRAIP调用的calculateDistanceForLat调用。细胞细节中的每个距离都是-0.001。

1 个答案:

答案 0 :(得分:0)

您肯定需要将mapVC作为数据源和委托。如果UITableViewController不允许您将其分配给其他本身,您可能需要考虑使用常规UIViewController并将UITableView放到它上面。如果将其设置为名为tableview的属性,那么执行tableVC.tableView.dataSource = mapVC;的tabbarcontroller中的代码仍然有效。

是的,您可以而且应该从tableVC中删除所有tableview委托和数据源代码,如果它正在调用那些,那么它不会调用mapVC中那些你想要的那些。

它可能会给你错误的距离,因为tableVC没有用户的位置来衡量。将表数据源附加到地图的另一个好理由。