ARC自定义委托奇怪的问题
Posted
技术标签:
【中文标题】ARC自定义委托奇怪的问题【英文标题】:ARC custom delegate strange issue 【发布时间】:2013-01-18 15:35:44 【问题描述】:好的,所以我有一个奇怪的问题,过去几个小时我一直在尝试解决:
我有一个用于 iPad 的简单故事板应用程序,它有两个视图控制器,FirstViewController
是主视图控制器,ModalViewController
出现在 Modal segue 上,它有一个名为 Done 的按钮。
我正在使用 ARC,并且视图控制器被指定用于 iPad。
我还有一个自定义委托UIModalViewControllerDelegate
,正如您猜想的那样,它是关闭模式并将数据传递回第一个视图控制器。
UIModalViewControllerDelegate.h
@protocol UIModalViewControllerDelegate <NSObject>
@required
-(void)btnDonePressed:(id)sender Values:(NSArray *)values;
@end
FirstViewController.h
@interface FirstViewController : UIViewController <UIModalViewControllerDelegate>
@private
ModalViewController *mvc;
@end
FirstViewController.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
// Custom initialization
return self;
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
mvc = [segue destinationViewController];
mvc.delegate = self;
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
#pragma UIModalViewControllerDelegate
-(void)btnDonePressed:(id)sender Values:(NSArray *)values
...
ModalViewController.h
@interface ModalViewController : UIViewController
__weak id<UIModalViewControllerDelegate> delegate;
@property (weak, nonatomic) id<UIModalViewControllerDelegate> delegate;
ModalViewController.m
@implementation ModalViewController
@synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
// Custom initialization
return self;
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(buttonPressed:)];
-(void) buttonPressed:(id) sender
[delegate btnDonePressed:sender Values:values];
现在,有几个非常有趣的问题:
1- 在为 segue 做准备时,在我设置 self.mvc.delegate = self;
后,调试器显示委托仍然为零(!)但是,当我使用 NSLog(@"%@", self.mvc.delegate);
时,我得到的指针地址不是零。
2- 上面的代码不起作用,因为在ModalViewController
中,委托始终为零。因此,[delegate btnDonePressed:sender Values:values];
永远不会执行。我尝试了所有我知道的可能会导致此问题的方法,但似乎没有任何效果。
3- 我想对委托进行强引用可能会解决此问题,但我不想违反模式并导致保留周期问题。
FirstViewController
中的私有变量ModalViewController *mvc;
是否存在生命周期问题?私有变量何时被取消?顺便说一句,我也尝试用@property (strong, nonatomic) ModalViewController *mvc;
替换它,但没有任何改变。
【问题讨论】:
如果您将委托 ivar 更改为声明为“__weak idid<UIModalViewControllerDelegate>delegate
,但由于我在过去几个小时内更改了很多代码,所以我只是在这里复制了错误的版本。但是,这并不能解决问题。 (我更新了上面的代码)
@rdelmar 是的,你是对的。我实际上更喜欢使用私有变量(我更新了上面的代码)。因为我不想从我们这边访问它。就生命周期而言,它应该没有任何区别,对吧?我的意思是私有变量与财产
【参考方案1】:
“我只是在这里复制了错误的版本。但是,这并不能解决问题。(我更新了上面的代码)”
既然你提到了复制粘贴。确保原始代码中有一个@synthesize
。这个问题看起来像是合成属性与私有变量名称不匹配。
@property (weak, nonatomic) id<UIModalViewControllerDelegate>delegate;
与@synthesize
结合声明的属性将使用名为delegate
的私有变量。如果您不小心遗漏了@synthesize
,将自动创建一个名为_delegate
的私有变量(注意下划线)。
在您的buttonPressed:
方法中,您可以直接访问私有变量delegate
。所以这可能总是返回 nil,因为访问器实际上使用下划线版本。
只是为了确保,要么删除手动声明的变量 delegate
,要么在您的 buttonPressed:
方法中使用 self.delegate
。看看会发生什么。
【讨论】:
感谢您的回答。这是深思熟虑的。我没有在原始代码中遗漏@synthesize,但它仍然不起作用。如果我删除 __weak idbuttonPressed:
中使用_delegate
【参考方案2】:
感谢大家的回答。我终于找到了解决这个问题的方法。
实际上,代码是完全正确的。问题在于 UINavigationController
,其中嵌入了模态视图控制器。
代替
myModalWindowViewController = [segue destinationViewController];
myModalWindowViewController.delegate = self;
我愿意
UINavigationController *navigationController = [segue destinationViewController];
myModalWindowViewController = (MyModalWindowViewController *)[navigationController.viewControllers objectAtIndex:0];
myModalWindowViewController.delegate = self;
我不知道当您选择嵌入在 NavigationController 中的 ViewController 时,DestinationViewController 是 NavigationController 而不是 ViewController。我的错!
【讨论】:
以上是关于ARC自定义委托奇怪的问题的主要内容,如果未能解决你的问题,请参考以下文章
如何处理自定义 UIViewController 委托 (ARC)?
在 ARC 中使用 Blocks 和以某种方式复制的奇怪内存泄漏