无法在 iOS 上使用自定义 @protocol
注意:以下是使用启用了自动引用计数(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 ARC 下,ivars 默认为
strong
。因此,错误告诉您,您已声明具有 __unsafe_unretained(分配)所有权的属性,其中底层 ivar 具有 __strong 所有权,这是非法的。为了避免该错误,您有 3 个选择:
__unsafe_unretained id; delegate;
@property (weak) id; delegate;
就我个人而言,我会省略 ivar 声明,这样您就可以在属性声明的一处获得所有权语义。
Under ARC ivars default to
strong
. So the erroris 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:__unsafe_unretained id <FileListDelegate> delegate;
@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.
似乎使用 :
你没有得到
FileListViewController
对象。查看它显示的消息:-[ImportViewController setDelegate:]: 无法识别的选择器发送到实例 0x6c7d430
这就是您的应用程序崩溃的原因。还尝试定义一个保留属性,而不仅仅是分配,以防委托在其他地方释放,您的应用程序不会崩溃。
It seems that with :
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.
我刚刚遇到了同样的问题,迫使我最终深入研究 ARC 文档。
为了澄清上面引用的 user756245 的答案,根据我的阅读,我不认为 iOS 5 改变了你不应该保留你的委托的最佳实践,因为这是一个很好的泄漏方式。我认为 __weak 和(weak)标记是编译器的注释,以便能够正确处理委托的生成代码。
I just ran across this same issue, forcing me to finally delve into the ARC documentation.
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.