如何将MapViewController设置为TableViewController的数据源以显示单元格中的距离 [英] How to setup a MapViewController as Datasource to a TableViewController for displaying distance in cells

查看:66
本文介绍了如何将MapViewController设置为TableViewController的数据源以显示单元格中的距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My app has a tabbarcontroller with a UIViewController (FirstViewController-calling it mapVC) with a mapview and a UITableViewController (SecondViewController-calling it tableVC). The app fetches data from web and puts it into CD-db and each VC executes a fetch to the db. Each entity is named Holiday (dont ask) and it has a lat and long property.

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

Here is the UITabBarController subclass which attempts to set the mapVC as datasource to 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的相关部分:

Here are the relevant parts of 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调用的方法.

The plotStoreLocations method is the only method call from a UIButton in the mapVC toolbar.

关于tableVC(SecondViewController)

As for 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;
}

最后一个我的位置:

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& nosit)方法,是否需要将其从tableVC中删除?

1) If I added the cFRAIP (noris & nosit) method in mapVC (the new datasource) do I need to remove it from tableVC?

2)如果我从tableVC中删除cFRAIP和其他2个方法(noris和nosit),则会崩溃,因为没有数据源.因此,数据源的tabbarcontroller分配似乎不起作用.

2) If I remove cFRAIP and the other 2 (noris and nosit) methods from tableVC, it crashes because there is no datasource. So the tabbarcontroller assignment of datasource doesnt seem to be working.

3)最后,如果必须从tableVC删除cFRAIP,我将失去UIViewBar tableview的功能.还是我错了?

3) Finally if I have to remove cFRAIP from tableVC, I will lose my ability to UISearchBar the tableview. Or am I wrong?

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

When I run the app, the mapVC is the selected vc. The UIButton in the toolbar that calls plotStoreLocations in mapVC is greyed out until the web fetch finishes. At this point the console logs the self.farsiman locations which are Holiday entities. And I can see all the entities log into the console.

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

When I click the plot button, the userLocation is logged correctly as specified in the plotStorePositions and the distance value for each annotation is correct. So the distance for each MKAnnotation is calculated correctly.

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

When I switch to the tableVC tab, the new self.dates array is logged in the console (because I currently have the tableVC do another CD-db fetch. And I get this for each pin location:

CFRAIP引脚中的位置已经是< + 15.50288611,-88.02716389> +/- 0.00m(速度-1.00 mps/课程-1.00)@ 1/24/13,8:20:39 PM Central Standard Time,userLocation is(null)

Already in CFRAIP pinLocations is <+15.50288611,-88.02716389> +/- 0.00m (speed -1.00 mps / course -1.00) @ 1/24/13, 8:20:39 PM Central Standard Time, userLocation is (null)

从CFRAIP调用的calculateDistanceForLat中调用的

.单元格细节中的每个距离都是-0.001.

which is called from the calculateDistanceForLat which is called by the CFRAIP. And every distance in the cell detail is -0.001.

推荐答案

您肯定需要使mapVC成为数据源和委托.如果UITableViewController不允许您将其分配给其他对象,则可以考虑使用常规的UIViewController并将UITableView放到该对象上.如果将其设置为名为tableview的属性,则执行tableVC.tableView.dataSource = mapVC;的tabbarcontroller中的代码仍将起作用.

You definitely need to make mapVC the datasource and delegate. If UITableViewController isn't letting you assign it to something other that itself you might want to consider using a regular UIViewController and drop a UITableView on to it. If you set it up as a property called tableview the code in tabbarcontroller that does tableVC.tableView.dataSource = mapVC; will still work.

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

Yes you can and should remove all tableview delegate and datasource code from your tableVC, if it is calling those then it isn't calling the ones in the mapVC which is what you want.

这可能是给您错误的距离,因为tableVC没有测量用户的位置.将表数据源附加到地图的另一个很好的理由.

It's probably giving you the wrong distance because tableVC doesn't have the user's location to measure from. Another good reason for having the table datasource attached to the map.

这篇关于如何将MapViewController设置为TableViewController的数据源以显示单元格中的距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆