从另一个类缩放 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的主要内容,如果未能解决你的问题,请参考以下文章