编译器无法看到UIImagePickerControllerDelegate协议的一致性

tob*_*jim 3 delegates protocols compiler-warnings ios

我错过了什么.这段代码运行正常,但我想清除所有编译器警告.

Sending 'GSBBuilderImageButton *const __strong' to parameter of incompatible type 'id<UINavigationControllerDelegate,UIImagePickerControllerDelegate>'
Run Code Online (Sandbox Code Playgroud)

在过去使用此警告消息的经验中,我从未注意到警告中提到了两个协议 - 并且公平地说,在这种情况下,我不知道为什么存在对UINavigationControllerDelegate的引用.

但这是我的界面:

#import <UIKit/UIKit.h>
#import "GSBImageButtonDelegate.h"

@interface GSBBuilderImageButton : UIButton <UIImagePickerControllerDelegate>
{
    UIPopoverController *popover;
    UIImage *imageData;
    NSURL *mediaURL;
    id <GSBBuilderImageButtonDelegate> _delegate;
}
@property (strong, nonatomic) NSURL *mediaURL;
@property (strong, nonatomic) UIImage *imageData;
@property (strong, nonatomic) id <GSBBuilderImageButtonDelegate> delegate;
- (void)removePicture;
- (void)setImageData:(UIImage *)theImageData;

@end
Run Code Online (Sandbox Code Playgroud)

重要的是@interface声明,其中包括UIImagePickerControllerDelegate采用.

在我的实现中我注意到了一点(我想在我写这篇文章的时候我没有使用setTarget:forAction:forControlState:因为这个类以UIView的形式开始):

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // really need to check to see that the touch ended while within our bounds

    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];

    [imagePicker setSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
    [imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
    [imagePicker setDelegate:self];
Run Code Online (Sandbox Code Playgroud)

所以我读到的方式是本地对象imagePicker被告知它的委托是GSBBuilderImageButton的这个实例,它在它的接口中声明它符合UIImagePickerControllerDelegate协议.这似乎是完全有效的,我们一直在做的事情.虽然我的GSBBuilderImageButton确实有自己的委托,但除非我做错了,否则不应该这样做.

当然,还有更多,包括可选协议方法的实现

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
Run Code Online (Sandbox Code Playgroud)

我正在以编程方式构建此按钮,因此为了完整性,这是我正在使用的init:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        [[self imageView] setContentMode:UIViewContentModeScaleAspectFill];
        UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(removePicture)];
        [self addGestureRecognizer:longPress];
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

(注意:不要挂断我对setImageData的定义...这是一个调用UIButton的setImage的包装器方法,但也有一些其他任务,它的遗产是相同的UIView遗产 - 对于这个应用程序的2.0版我会覆盖setImage:!

ric*_*ter 13

这只是警告消息说什么:UIImagePickerControllerdelegate财产预计这符合一个对象UIImagePickerControllerDelegateUINavigationControllerDelegate协议.这是因为图像选择器UI包括导航控制器; 该协议中的方法是可选的,因此如果您不需要对它们执行任何操作,则无需实现它们.

但是你仍然需要声明对两种协议的一致性:

@interface GSBBuilderImageButton : UIButton <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
Run Code Online (Sandbox Code Playgroud)

其余代码与编译器警告无关.


更新:这是一个相关的提示.如果仅在类的实现中使用协议一致性,则无需在头文件中声明它.您可以在.m文件中的类扩展中声明一致性:

@interface GSBBuilderImageButton () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@end
Run Code Online (Sandbox Code Playgroud)