【问题标题】:Compile-time error: No known instance method for selector 'setDetailItem:'编译时错误:选择器“setDetailItem:”没有已知的实例方法
【发布时间】:2014-01-06 13:34:31
【问题描述】:

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

然后在 Main.storyboard 中,我将 UILabel 替换为 UIWebView,并在 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我尝试获取传递的NSDictionarydict并加载webView中的URL:

#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 类型,它不应该接受任何选择器吗?

【问题讨论】:

  • 它将接受任何选择器,但选择器仍需要在某处声明。

标签: ios iphone objective-c selector


【解决方案1】:

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

当您通过

声明您的财产时
@property (strong, nonatomic) NSDictionary *detailItem;

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

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

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

查看有关 Apple 文档中的属性的更多信息,或浏览一些链接,例如 this

【讨论】:

  • 是的,- (void)setDetailItem:(NSDictionary*)newDict; 缺少 DetailViewController.h
  • 谢谢!所以根本原因是我调用了“私有”方法:-)
【解决方案2】:

问题在于,在编译器命中的地方

[[segue destinationViewController] setDetailItem:dict];

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多