从另一个类缩放 MkMapView

Posted

技术标签:

【中文标题】从另一个类缩放 MkMapView【英文标题】:Zooming MkMapView from another class 【发布时间】:2012-10-20 09:35:33 【问题描述】:

我有一个在 xib 中设计的带有 UITableView *myTable 和 MKMapView *myMap 的 ViewController,但是表委托/数据源和地图委托在另一个名为 SubClass 的类中。当我在 ViewController 中按下一个按钮时,子类从 xml 远程文件中解析表格单元的纬度和经度,现在我想在每次选择 myTable 的行时将 myMap 缩放到这个坐标:嗯,我找不到方法从子类调用这个缩放。这是我的简化代码:

ViewController.h

// ViewController.h

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "SubClass.h"

@interface ViewController : UIViewController 
    IBOutlet UITableView *myTable;
    IBOutlet MKMapView *myMap;
    SubClass *subClassIstance;


- (void)buttonPressed:(id)sender
@property (nonatomic, retain) IBOutlet MKMapView *myMap;

ViewController.m

// in ViewController.m

- (void)buttonPressed:(id)sender 
    subClassIstance = [[SubClass alloc] init];
    myTable.delegate = SubClass;
    myTable.dataSource = SubClass;
    [myTable reloadData];

    subClassIstance = [[SubClass alloc] loadMap:myMap];

子类.h

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

@interface SubClass : NSObject <UITableViewDataSource, UITableViewDelegate, MKMapViewDelegate> 


- (void)loadValues;
- (id)loadMap:(MKMapView *)mapView;
- (id)zoomTheMap:(NSMutableString *)string1 :(NSMutableString *)string2 :(MKMapView *)mapView; // IS IT RIGHT???

子类.m

- (id)init
    self = [super init];
 if ( self != nil ) 
     [self loadValues];
 
    return self;


- (void)loadValues 

  // CODE TO PARSE VALUES OF LONGITUDE AND LATITUDE TO PASS IN THE TABLE CELLS
 latitudeFromLoadValues = // NSMutableString parsed value from a xml remote file
 longitudeFromLoadValues = // NSMutableStringparsed value from a xml remote file


- (id)loadMap:(MKMapView *)mapView

    if (self) 
    mapView.delegate = self; // CODE TO LOAD ANNOTATIONS AND OTHER STUFF. IT WORKS!
    
    return self;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

latitudeFromLoadValues = [dataParsed objectAtIndex:indexPath.row];
longitudeFromLoadValues = [data2Parsed objectAtIndex:indexPath.row];
[self zoomTheMap:latitudeFromLoadValues :longitudefromLoadValues :???]; // IS IT CORRECT? WHAT IS THE RIGHT *MKMAPVIEW?


- (id)zoomTheMap:(NSMutableString *)string1 :(NSMutableString *)string2 :(MKMapView *)mapView 

    NSLog(@"%@",string1);
    NSLog(@"%@",string2);

    MKCoordinateRegion region;
    region.center.latitude = [string1 floatValue];
    region.center.longitude = [string2 floatValue];
    region.span.latitudeDelta = 2.0;
    region.span.longitudeDelta = 2.0;

    // I KNOW, I HAVE TO CALL myMap from ViewController! But with an istance?

    mapView.delegate = self;
    mapView.region = region;    

    return self;

好吧,剩下的代码可以工作了!我可以看到 ViewController 中的 *myMap 加载了在 SubClass 中声明的一些注释,并且 *myTable 加载了填充有在 SubClass 中解析的纬度和经度的单元格;我还可以看到在 string1 和 string2 中传递的正确经度和纬度,但是当我选择单个表格单元格时,我没有看到 myMap 缩放,我认为我使用了错误的方法。请你帮帮我好吗?

【问题讨论】:

【参考方案1】:

loadMap 不应该返回 self,只有 init 方法应该这样做。 在buttonPressed 中,您分配一个新的子类,对其做一些事情,然后分配另一个子类并调用它的loadMap 函数。最后一行应该是[subClassIstance loadMap:myMap],但您还需要在每次按下该按钮时重新考虑分配一个新的子类。

我认为您确实以错误的方式解决了这个问题。为什么需要一个子类(BTW 的名字很糟糕,它没有说明它的用途)?它扩展了什么类?如果 ViewController 有 MKMapView,它通常是向地图发出命令的那个。我可以理解你有一个单独的 tableview 数据源,但不是其余的。如果你让 VC 成为它自己的表和映射委托,你会简化很多事情。

如果你真的想在你的代码中有一个子类,那么你应该在你在 buttonPressed 的第一行创建的实例上调用 loadMap

- (void)buttonPressed:(id)sender 
    subClassIstance = [[SubClass alloc] init];
    myTable.delegate = SubClass;
    myTable.dataSource = SubClass;
    [myTable reloadData];

    [subClassIstance loadMap:myMap];

你的 loadMap 看起来像

- (void)loadMap:(MKMapView *)mapView

    mapView.delegate = self; 

但是,如果这就是 loadMap 的全部内容,您是否不需要一个函数,您可以让 buttonPressed 完成所有工作。

- (void)buttonPressed:(id)sender 
    subClassIstance = [[SubClass alloc] init];
    myTable.delegate = SubClass;
    myTable.dataSource = SubClass;
    [myTable reloadData];

    myMap.delegate = subClassIstance;

初始化函数示例:

- (id)initiWithMapView: (MKMapView)* mapView

    self = [super init];
    if(self)
    
       theMap = mapView;
       theMap.delegate = self;
       [self loadValues];
       ....
    
    return self;
 

如果您使用它,您将不必一直设置地图委托或返回 self,您可以在每个函数中使用 theMap(如您的答案中所声明的)。

【讨论】:

谢谢你 Craig,obv 这里的“ViewController”和“SubClass”是通用名称来表示我的类,而不是我的代码中使用的真实名称。我也在使用 -(id)loadMap(MKMapView )mapView 然后 [return self] 从 ViewController 使用 loadMap:myMap 调用此方法,但我知道这是一种复杂的方式:我将重新考虑编写代码在 VC 中映射委托.. 啊,我现在得到了子类名称。我关于 loadMap 返回 self 的观点仍然成立。我将在上面更新我的答案,向您展示您可以做出的两项改进。 是的,您编辑的答案与我的代码类似,但如果在 - (id)loadMap:(MKMapView *)mapView 方法中我不写“return self”; XCode 给出“警告:控制到达非无效函数的结尾” 那是因为我忘了告诉你将 loadmap 的声明更改为不返回任何内容。我现在已经解决了这个问题并添加了一个 init 函数。【参考方案2】:

好吧,对于那些感兴趣的人,我找到了一个简单的解决方案:首先,我在我的 SubClass.h 中定义了一个通用的 MKMapView *theMap,现在看起来像:

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

@interface SubClass : NSObject <UITableViewDataSource, UITableViewDelegate, 

MKMapViewDelegate> 
        MKMapView *theMap // NEW CODE!!!
    

- (void)loadValues;
- (id)loadMap:(MKMapView *)mapView;
- (id)zoomTheMap:(NSMutableString *)string1 :(NSMutableString *)string2 :(MKMapView *)mapView;

在 loadMap 方法中,我将 *theMap 与 VC 中的 SubClassIstance 调用的 mapView 进行了比较(我想要缩放的 *myMap),所以现在我们有了:

- (id)loadMap:(MKMapView *)mapView

    if (self) 
    mapView.delegate = self; 
    theMap = mapView; // NEW CODE !!!

    // CODE TO LOAD ANNOTATIONS AND OTHER STUFF. IT WORKS!
    
    return self;

在 didSelectRowAtIndexPath 中,我已将 *theMap 作为 zoomTheMap 方法的 mapView 参数传递:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

latitudeFromLoadValues = [dataParsed objectAtIndex:indexPath.row];
longitudeFromLoadValues = [data2Parsed objectAtIndex:indexPath.row];
[self zoomTheMap:latitudeFromLoadValues :longitudefromLoadValues :theMap]; // NEW CODE !!!

zoomTheMap 方法没有改变,现在,“神奇地”,每次我按下表格的一行时,在 VC xib 中设计的 *myMap(但在子类中有委托)都会放大存储在细胞:

- (id)zoomTheMap:(NSMutableString *)string1 :(NSMutableString *)string2 :(MKMapView *)mapView 

    MKCoordinateRegion region;
    region.center.latitude = [string1 floatValue];
    region.center.longitude = [string2 floatValue];
    region.span.latitudeDelta = 2.0;
    region.span.longitudeDelta = 2.0;

    mapView.delegate = self; // here mapView is *theMap passed in didSelectRowAtIndexPath, AKA original mapView istance used to delegate *myMap in VC
    [mapView setRegion:region animated:YES];   

    return self;

也许它不是一种“优雅”的方式,但它现在有效! ;=)

【讨论】:

你的代码到处都是。您无需在编写的每个函数上都返回 self。就在函数调用它时,它需要一个参考以供以后使用。如果您声明您的功能为-(void).... 而不是-(id)....,那么您可以删除return self 行。然后,不要每次都设置委托。在初始化期间执行一次。最后,如果theMap在初始化时也设置了,你就不需要传入zoomTheMap,直接使用theMap即可。 谢谢克雷格,我也按照您的建议“清理”了我的代码... ;=)

以上是关于从另一个类缩放 MkMapView的主要内容,如果未能解决你的问题,请参考以下文章

从另一个活动返回时,MapFragment 的地图加载滞后

从另一个类访问 IBOutlet

从另一个类访问 UI 图像

如何从另一个类调用方法函数?

Python从另一个类导入类[关闭]

js获取当前页面的缩放比