协议中无法识别的选择器

时间:2013-11-26 15:36:49

标签: ios objective-c selector protocols arcgis

更新:发现问题,找到解决方案并标记为答案。

问题是我使用超类的静态方法进行初始化,从而将其转换为超类而不是子类。

END UPDATE:

我有一个协议,一个实现该协议的类,然后是一个创建调用协议方法的协议类实例的类。我在调用该协议方法时收到“无法识别的选择器发送到实例...”。

注意:我使用ArcGIS显示地图,但这与我的问题无关。

协议方法(layerName)稍后在运行时在另一个实现LayerProtocol的对象上工作。

示例代码:

@protocol LayerProtocol <NSObject>
- (NSString *) layerName;
@end

@interface StreetLayer: AGSTiledMapServiceLayer<LayerProtocol>
@end

@implementation StreetLayer

- (id) init
{
    self = [AGSTiledMapServiceLayer tiledMapServiceLayerWithURL:
            [NSURL URLWithString: [NSString stringWithFormat:
                               @"%@%@",
                               @"https://server.arcgisonline.com/ArcGIS/",
                               @"rest/services/World_Street_Map/MapServer"]
             ]];
    return self;
}
- (NSString *) layerName
{
    return @"Street Layer";
}
@end

@interface MapContainerViewController: UIViewController
@property (nonatomic) AGSMapView * mapView;
@property (nonatomic) StreetLayer * layer;
@end

@implementation MapContainerViewController
- (void) viewDidLoad
{
    _mapView = [[AGSMapView alloc] init];
    _layer = [[StreetLayer alloc] init];
    [mapView addMapLayer:_layer withName:[_layer layerName]];
}

访问[_layer layerName]

时发生错误

我觉得我错过了一些非常明显的东西。

我知道AGSLayer可以访问图层的名称,这与问题无关。

此外,我使用了[_layer respondsToSelector:@selector(layerName)],但未通过检查。

STACK TRACE:

* 由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:' - [AGSTiledMapServiceLayer layerName]:无法识别的选择器发送到实例0xbe7ef90'

* 第一次抛出调用堆栈: (

0   CoreFoundation                      0x035105e4 __exceptionPreprocess + 180
1   libobjc.A.dylib                     0x032938b6 objc_exception_throw + 44
2   CoreFoundation                      0x035ad903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3   CoreFoundation                      0x0350090b ___forwarding___ + 1019
4   CoreFoundation                      0x035004ee _CF_forwarding_prep_0 + 14
5   MyProject                            0x00061d95 -[MapContainerViewController mapTypeToggled:] + 677
6   libobjc.A.dylib                     0x032a5874 -[NSObject performSelector:withObject:withObject:] + 77
7   UIKit                               0x01522c8c -[UIApplication sendAction:to:from:forEvent:] + 108
8   UIKit                               0x01522c18 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
9   UIKit                               0x0161a6d9 -[UIControl sendAction:to:forEvent:] + 66
10  UIKit                               0x0161aa9c -[UIControl _sendActionsForEvents:withEvent:] + 577
11  UIKit                               0x01619d4b -[UIControl touchesEnded:withEvent:] + 641
12  UIKit                               0x015600cd -[UIWindow _sendTouchesForEvent:] + 852
13  UIKit                               0x01560d34 -[UIWindow sendEvent:] + 1232
14  UIKit                               0x01534a36 -[UIApplication sendEvent:] + 242
15  UIKit                               0x0151ed9f _UIApplicationHandleEventQueue + 11421
16  CoreFoundation                      0x034998af __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
17  CoreFoundation                      0x0349923b __CFRunLoopDoSources0 + 235
18  CoreFoundation                      0x034b630e __CFRunLoopRun + 910
19  CoreFoundation                      0x034b5b33 CFRunLoopRunSpecific + 467
20  CoreFoundation                      0x034b594b CFRunLoopRunInMode + 123
21  GraphicsServices                    0x051d49d7 GSEventRunModal + 192
22  GraphicsServices                    0x051d47fe GSEventRun + 104
23  UIKit                               0x0152194b UIApplicationMain + 1225
24  GmcSeeds                            0x00073b1d main + 141
25  libdyld.dylib                       0x03a7f725 start + 0

) libc ++ abi.dylib:以NSException类型的未捕获异常终止

- (void) mapTypeToggled:(id)sender
{
_streetViewToggled = !_streetViewToggled;
if (_streetViewToggled)
{
    // show street view
    [_mapView removeMapLayer:_satelliteLayer];
    [_mapView insertMapLayer:_streetLayer
                    withName:[_streetLayer layerName]
                     atIndex:0];
}
else
{
    // show satellite view
    [_mapView removeMapLayer:_streetLayer];
    [_mapView insertMapLayer:_satelliteLayer
                    withName:[_satelliteLayer layerName]
                     atIndex:0];
}
}

1 个答案:

答案 0 :(得分:3)

一种选择是替换此

- (id) init
{
    self = [AGSTiledMapServiceLayer tiledMapServiceLayerWithURL:
            [NSURL URLWithString: [NSString stringWithFormat:
                               @"%@%@",
                               @"https://server.arcgisonline.com/ArcGIS/",
                               @"rest/services/World_Street_Map/MapServer"]
             ]];
    return self;
}

用这个

- (id) init
{
    self = [[self class] tiledMapServiceLayerWithURL:
            [NSURL URLWithString: [NSString stringWithFormat:
                               @"%@%@",
                               @"https://server.arcgisonline.com/ArcGIS/",
                               @"rest/services/World_Street_Map/MapServer"]
             ]];
    return self;
}

最好还有一个用于创建街道图层的类方法:

@implementation StreetLayer

+ (instancetype)streetLayer
{
    return [[self class] tiledMapServiceLayerWithURL:
                [NSURL URLWithString: [NSString stringWithFormat:
                                   @"%@%@",
                                   @"https://server.arcgisonline.com/ArcGIS/",
                                   @"rest/services/World_Street_Map/MapServer"]
                 ]];

}

@end