我正在开发一款具有主视图的iPad应用程序(在本例中为MKMapView),其中包含一个包含UITableViewController的PopoverView控制器。 UITableview中的内容包含许多可变元素,我需要在MapView上删除注释引脚。这些变量根据选择的行而变化。我的想法是使用代表来完成这个,但我正在努力实现它。
我在showIncidentList方法中声明了delegate(参见附上的代码)。我的问题是,这个自定义委托是否适合这个期望的结果,如果是这样,我错过了什么,这将允许我在委托中传达信息,并使用委托的更新信息在主视图上调用plotCallLocations方法。
相关代码:
SearchViewController.h // popoverViewController类
@protocol IncidentPickerDelegate <NSObject>
- (void)incidentSelected:(NSMutableArray *)incidentDetail;
@end
@interface SearchViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
__weak id<IncidentPickerDelegate> _delegate;
}
@property (nonatomic, retain) NSMutableArray *incidentDetails;
@property (nonatomic, weak) id<IncidentPickerDelegate> delegate;
@end
SearchViewController.m
#import "TwitterSearchViewController.h"
#import "CallViewController.h"
@implementation SearchViewController
@synthesize delegate = _delegate;
@synthesize incidentDetails= _incidentDetails;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
_incidentDetails = [[NSMutableArray alloc] initWithObjects:[textItems objectAtIndex:0], [textItems objectAtIndex:1], lat, lon, nil]; //textItems is an NSArray of parsed JSON data, lat and lon are int's
NSLog(@"_delegate = %@", _delegate);
if ([_delegate respondsToSelector:@selector(incidentSelected:)]) {
NSMutableArray *incidentDet = _incidentDetails;
[_delegate incidentSelected:incidentDet];
NSLog(@"incidentDetail ----> %@", incidentDet);
}
@end
CallViewController.h // MainViewController
#import "SearchViewController.h"
@interface CallViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate, UIAlertViewDelegate, IncidentPickerDelegate> {
}
@property (nonatomic, retain) UIPopoverController *incidnetListPopover;
@property (nonatomic, retain) SearchViewController *incidentPicker;
-(IBAction)showIncidentList:(id)sender;
CallViewController.m
#import "CallViewController.h"
#import "SearchViewController.h"
@implementation CallViewController
@synthesize incidnetListPopover = _incidnetListPopover;
@synthesize incidentPicker = _incidentPicker;
UIStoryboard* sb = [UIStoryboard storyboardWithName:@"MainStoryboard"
bundle:nil];
if (_incidentPicker == nil) {
self.incidentPicker = [sb instantiateViewControllerWithIdentifier:@"SearchViewController"];
_incidentPicker.delegate = self;
self.incidnetListPopover = [[UIPopoverController alloc]
initWithContentViewController:_incidentPicker];
}
[self.incidnetListPopover presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
- (void)incidentSelected:(NSMutableArray *)incidentDetail {
// for (id<MKAnnotation> annotation in _mapView.annotations) {
// [_mapView removeAnnotation:annotation];
NSLog(@"plotCall called");
NSNumber * latitude = [incidentDetail objectAtIndex:2];
NSNumber * longitude = [incidentDetail objectAtIndex:3];
NSString * name = [incidentDetail objectAtIndex:1];
NSString * address = [incidentDetail objectAtIndex:0];
CLLocationCoordinate2D coordinate;
coordinate.latitude = latitude.doubleValue;
coordinate.longitude = longitude.doubleValue;
CallLocation *annotation = [[CallLocation alloc] initWithName:name address:address coordinate:coordinate];
[_mapView addAnnotation:annotation];
[self.incidnetListPopover dismissPopoverAnimated:YES];
}
答案 0 :(得分:1)
自定义委托方法适用于这种情况。
主要问题是CallViewController
没有实现IncidentPickerDelegate
协议incidentSelected:
中指定的确切方法。 (顺便说一句,我认为“TwitterSearchViewController”是一个拼写错误,应该是“SearchViewController”,反之亦然。)
即使CallViewController
的方法plotCallLocations:
也采用了数组,但它并未命名为完全 incidentSelected:
(它需要)。
你应该收到一些编译器警告。
因此当SearchViewController
调用该协议方法时,它可能会因“无法识别的选择器”错误而崩溃。
以下是一些解决方案(第一个是最简单的):
CallViewController
中,将plotCallLocations:
更改为incidentSelected:
incidentSelected:
更改为plotCallLocations:
CallViewController
中添加incidentSelected:
方法,然后致电plotCallLocations:
单独(不会引起问题但是),在SearchViewController
中,而不是检查代理是否为nil
,最好检查委托是否实际上具有您将使用{{1}调用的方法}}。
要做到这一点,首先您必须respondsToSelector:
实施IncidentPickerDelegate
协议:
NSObject
现在在@protocol IncidentPickerDelegate<NSObject>
,而不是检查委托是否为SearchViewController
:
nil