编译时错误:选择器'setDetailItem:'没有已知的实例方法

时间:2014-01-06 13:34:32

标签: ios iphone objective-c selector

在Xcode 5.0.2中,我为iPhone创建了一个空白的Detail-Master应用程序。

然后在Main.storyboard中,我用UIWebView替换UILabel,并在DetailViewController.h中将其声明为webView

我也会将id *defaultItem替换为NSDictionary *dict

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController
@property (strong, nonatomic) NSDictionary *dict;
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end

MasterViewController.m我硬编码“词典词典”_menu

#import "MasterViewController.h"
#import "DetailViewController.h"

static NSString *kLabel   = @"label";
static NSString *kAuthUrl = @"auth_url";

@interface MasterViewController () {
    NSDictionary *_menu;
    NSArray *_keys;
}
@end

@implementation MasterViewController

- (void)awakeFromNib
{
    [super awakeFromNib];

    _menu = @{
              @"FB": @{
                      kLabel:   @"Facebook",
                      kAuthUrl: @"https://graph.facebook.com/oauth/authorize?",
                      },
              @"GG": @{
                      kLabel:   @"Google+",
                      kAuthUrl: @"https://accounts.google.com/o/oauth2/auth?",
                      },
              @"MR": @{
                      kLabel:   @"Mail.ru",
                      kAuthUrl: @"https://connect.mail.ru/oauth/authorize?",
                      },
              @"OK": @{
                      kLabel:   @"Odnoklassniki",
                      kAuthUrl: @"http://www.odnoklassniki.ru/oauth/authorize?",
                      },
              @"VK": @{
                      kLabel:   @"VKontakte",
                      kAuthUrl: @"http://oauth.vk.com/authorize?",
                      },
            };
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _keys.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    NSString *key = _keys[indexPath.row];
    NSString *label = _menu[key][kLabel];
    cell.textLabel.text = label;
    return cell;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSString *key = _keys[indexPath.row];
        NSDictionary *dict = _menu[key];
        [[segue destinationViewController] setDetailItem:dict]; // XXX the error line
    }
}

@end

最后在DetailViewController.m我尝试接受传递的NSDictionary dict并在webView中加载网址:

#import "DetailViewController.h"

static NSString *kLabel   = @"label";
static NSString *kAuthUrl = @"auth_url";

@interface DetailViewController ()
- (void)configureView;
@end

@implementation DetailViewController

#pragma mark - Managing the detail item

- (void)setDetailItem:(NSDictionary*)newDict
{
    if (_dict != newDict) {
        _dict = newDict;

        [self configureView];
    }
}

- (void)configureView
{
    if (_dict) {
        NSURL *url = [NSURL URLWithString:_dict[kAuthUrl]];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [_webView loadRequest:request];
    }
}

@end

不幸的是我在Xcode中遇到了编译时错误:

  

MasterViewController.m:没有已知的选择器'setDetailItem:'

的实例方法

这一行:

    [[segue destinationViewController] setDetailItem:dict];

为什么会这样?

UIStoryboardSegue类的destinationViewController属性被声明为类型id,它不应该接受任何选择器吗?

2 个答案:

答案 0 :(得分:2)

编译时错误是因为您既没有在DetailViewController.h文件中声明该选择器,也没有使用NSDictionary的名称声明*detailItem的任何属性。

当您通过

申报财产时
@property (strong, nonatomic) NSDictionary *detailItem;

,编译器会自动生成一个setter方法,你可以覆盖

- (void)setDetailItem:(NSDictionary*)detailItem{
}

如果您要将自己的财产设为dict,请尝试-(void)setDict:(NSDictionary*)dict{}

查看Apple文档中有关属性的详情,或浏览this等链接。

答案 1 :(得分:1)

问题在于编译器点击

[[segue destinationViewController] setDetailItem:dict];

它不知道声明setDetailItem:任何类如果找到声明为id的对象,它将搜索所有它已知的匹配选择器使用声明,如果找不到,它会发出你看到的错误。

您需要确保将声明属性(或方法)setDetailItem:的类的头文件导入.m文件。然后它将编译。