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

发布于 2024-11-25 12:28:40 字数 2282 浏览 2 评论 0原文

注意:以下是使用启用了自动引用计数(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 属性'delegate'的现有 ivar 'delegate' 必须是 __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) 和 __weak 会起作用?我不 理解为什么这有效,因为我发现它谷歌搜索并且没有 解释。
  • 为什么我不能使用它来设置我的委托 '[fileListViewController setDelegate:self];' ?似乎是 编译器不知道“委托”存在。

Note: the below is using iOS with Automatic Reference Counting (ARC) enabled. I think ARC may have a lot to do with why it isn't working as this is set up as per examples i've found via google.

I am trying to create a protocol to notify a delegate of the filename the user selects from a 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;

This gives an error at the

@synthesize delegate;

line which is "FileListViewController.m: error: Automatic Reference Counting Issue: Existing ivar 'delegate' for unsafe_unretained property 'delegate' must be __unsafe_unretained"

If i change FileListViewController.h putting __weak and (weak) then it will run.

@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

But when I try to set the delegate the app crashes. A view called 'ImportViewController' is creating a view from 'FileListViewController' and setting the delegate to itself (ImportViewController) so I can implement my custom protocol of 'didSelectFileName'. The error I get is;

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ImportViewController setDelegate:]: unrecognized selector sent to instance 0x6c7d430'

The code I am running is;

ImportViewController.m

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

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

}

My Questions are:

  • Why does putting (weak) and __weak in make it work? I don't
    understand why this works as I found it googling and there wasn't an
    explanation.
  • Why can't I set my delegate using this
    '[fileListViewController setDelegate:self];' ? It seems like the
    compiler doesn't know 'delegate' exists.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

想挽留 2024-12-02 12:28:40

在 ARC 下,ivars 默认为 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。 ivar 将隐式声明为与您的财产相匹配的所有权。
  2. 定义 ivar 以匹配您的(分配)属性声明:__unsafe_unretained id; delegate;
  3. 定义属性以匹配 ivar 的隐式 __strong 所有权:@property (weak) id; delegate;

就我个人而言,我会省略 ivar 声明,这样您就可以在属性声明的一处获得所有权语义。

Under ARC ivars default to strong. So the error

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

is telling you that you've declared a property with __unsafe_unretained (assign) ownership, where the underlying ivar has __strong ownership, which is illegal. To avoid the error, you have 3 options:

  1. Omit the ivar. It's not necessary to declare an ivar for a synthesized property. The ivar will be declared implicitly with ownership matching your property.
  2. Define the ivar to match your (assign) property declaration: __unsafe_unretained id <FileListDelegate> delegate;
  3. Define the property to match the ivar's implicit __strong ownership: @property (weak) id <FileListDelegate> delegate;

Personally, I'd omit the ivar declaration so you have the ownership semantics in one place, on the property declaration.

单挑你×的.吻 2024-12-02 12:28:40

似乎使用 :

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

你没有得到 FileListViewController 对象。查看它显示的消息:

-[ImportViewController setDelegate:]: 无法识别的选择器发送到实例 0x6c7d430

这就是您的应用程序崩溃的原因。还尝试定义一个保留属性,而不仅仅是分配,以防委托在其他地方释放,您的应用程序不会崩溃。

It seems that with :

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

you didn't get an FileListViewController object. Look at the message it says :

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

and that why your app crashes. Also try to define a retain property, instead of just assign, in case the delegate is deallocated elsewhere, your app won't crash.

我很坚强 2024-12-02 12:28:40

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

还尝试定义一个保留属性,而不仅仅是分配,以防委托在其他地方释放,您的应用程序不会崩溃。

为了澄清上面引用的 user756245 的答案,根据我的阅读,我不认为 iOS 5 改变了你不应该保留你的委托的最佳实践,因为这是一个很好的泄漏方式。我认为 __weak 和(weak)标记是编译器的注释,以便能够正确处理委托的生成代码。

I just ran across this same issue, forcing me to finally delve into the ARC documentation.

Also try to define a retain property, instead of just assign, in case the delegate is deallocated elsewhere, your app won't crash.

To maybe clarify the above quote from user756245 's answer, based on my reading I don't think that iOS 5 has changed the best practice that you shouldn't be retaining your delegate as this is a good way to leak. I think the __weak and (weak) tokens are annotations for the compiler for the sake of being able to correctly deal with generating code for the delegate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文