无法在iOS上使用自定义@protocol

时间:2011-07-21 08:34:43

标签: objective-c cocoa-touch protocols

注意:以下是使用启用了自动引用计数(ARC)的iOS。我认为ARC可能与它不起作用有很大关系,因为这是根据我通过谷歌找到的例子设置的。

我正在尝试创建一个协议来通知代理用户从UITableView中选择的文件名。

FileListViewController.h

@protocol FileListDelegate <NSObject>
- (void)didSelectFileName:(NSString *)fileName;

@end

@interface FileListViewController : UITableViewController
{
    @private
        NSArray *fileList;
        id <FileListDelegate> delegate;
}
@property (nonatomic, retain) NSArray *fileList;
@property (nonatomic, assign) id <FileListDelegate> delegate;

@end

FileListViewController.m

#import "FileListViewController.h"

@implementation FileListViewController

@synthesize fileList;
@synthesize delegate;

这会在

处出错
@synthesize delegate;

行是“FileListViewController.m:错误:自动引用计数问题:unsafe_unretained属性'委托'的现有ivar'委托'必须是__unsafe_unretained”

如果我改变FileListViewController.h放置__weak和(弱)然后它将运行。

@protocol FileListDelegate <NSObject>
- (void)didSelectFileName:(NSString *)fileName;

@end

@interface FileListViewController : UITableViewController
{
    @private
        NSArray *fileList;
        __weak id <FileListDelegate> delegate;
}
@property (nonatomic, retain) NSArray *fileList;
@property (weak) id <FileListDelegate> delegate;

@end

但是当我尝试设置代理时,应用程序崩溃了。一个名为'ImportViewController'的视图正在从'FileListViewController'创建一个视图并将委托设置为自己(ImportViewController),因此我可以实现我的自定义协议'didSelectFileName'。我得到的错误是;

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

我正在运行的代码是;

ImportViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    FileListViewController *fileListViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"filelist"];

    [fileListViewController setDelegate:self];
    [self.navigationController pushViewController:fileListViewController animated:YES];

}

我的问题是:

  • 为什么把(弱)和__weak让它起作用?我不 理解为什么这个工作,因为我发现它谷歌搜索,没有 说明。
  • 为什么我不能使用它设置我的委托 '[fileListViewController setDelegate:self];' ?好像是 编译器不知道'委托'存在。

3 个答案:

答案 0 :(得分:13)

在ARC下,默认为strong。所以错误

Automatic Reference Counting Issue: Existing ivar 'delegate' for unsafe_unretained property 'delegate' must be __unsafe_unretained"

告诉您,您已声明具有__unsafe_unretained(分配)所有权的属性,其中基础ivar具有__strong所有权,这是非法的。为避免错误,您有3个选项:

  1. 忽略伊娃。没有必要为合成属性声明ivar。 ivar将隐含声明,所有权与您的财产相匹配。
  2. 定义ivar以匹配您的(assign)属性声明:__unsafe_unretained id <FileListDelegate> delegate;
  3. 定义属性以匹配ivar的隐式__strong所有权:@property (weak) id <FileListDelegate> delegate;
  4. 就个人而言,我会省略ivar声明,因此您可以在属性声明的一个地方拥有所有权语义。

答案 1 :(得分:4)

似乎与:

FileListViewController *fileListViewController =
    [self.storyboard instantiateViewControllerWithIdentifier:@"filelist"];

你没有得到FileListViewController个对象。看看它说的信息:

-[ImportViewController setDelegate:]: unrecognized selector sent to instance 0x6c7d430

这就是你的应用崩溃的原因。还尝试定义一个retain属性,而不是仅仅分配,以防代理在其他地方被释放,你的应用程序不会崩溃。

答案 2 :(得分:1)

我刚遇到同样的问题,迫使我最终深入研究ARC文档。

  

还尝试定义一个retain属性,而不是仅仅分配,如果在其他地方取消分配委托,你的应用程序不会崩溃。

为了澄清用户756245回答的上述引用,根据我的阅读,我不认为iOS 5已经改变了你不应该保留你的代表的最佳做法,因为这是一个很好的泄密方法。我认为__weak和(弱)令牌是编译器的注释,以便能够正确处理为委托生成代码。