[英]Custom delegate only works if directly called from UIButton selector ARC retain issue
[英]ARC custom delegate strange issue
好的,所以在過去的幾個小時里,我一直想找出一個奇怪的問題:
我有一個適用於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);
我得到的指針的地址不是nil。
2-上面的代碼不起作用,因為在ModalViewController
,委托始終為nil。 因此, [delegate btnDonePressed:sender Values:values];
將永遠不會執行。 我嘗試了所有可能導致此問題的方法,但似乎沒有任何效果。
3-我猜想對委托人有充分的參考可以解決此問題,但我不想違反此模式並引起保留周期問題。 是否私有變量ModalViewController *mvc;
在FirstViewController
有生命周期問題嗎? 私有變量什么時候被清除? 順便說一句,我也試圖用@property (strong, nonatomic) ModalViewController *mvc;
代替它@property (strong, nonatomic) ModalViewController *mvc;
但什么都沒有改變。
“我只是在這里復制了錯誤的版本。但是,這不能解決問題。(我更新了上面的代碼)”
由於您提到復制粘貼。 確保原始代碼中包含@synthesize
。 此問題看起來像是合成屬性與私有變量名稱的不匹配。
@property (weak, nonatomic) id<UIModalViewControllerDelegate>delegate;
與@synthesize
結合聲明的屬性將使用名為delegate
的私有變量。 如果您不小心遺漏了@synthesize
,則會自動創建一個名稱為_delegate
的私有變量(請注意下划線)。
在buttonPressed:
方法中,可以直接訪問私有變量delegate
。 因此,由於訪問器實際上使用的是帶下划線的版本,因此該返回值始終為nil。
只需確保刪除手動聲明的變量delegate
或在buttonPressed:
方法中使用self.delegate
。 走着瞧吧。
謝謝大家的回答。 我終於找到了解決這個問題的方法。
實際上,該代碼是完全正確的。 問題是UINavigationController
,其中嵌入了Modal View Controller。
代替
myModalWindowViewController = [segue destinationViewController];
myModalWindowViewController.delegate = self;
我做
UINavigationController *navigationController = [segue destinationViewController];
myModalWindowViewController = (MyModalWindowViewController *)[navigationController.viewControllers objectAtIndex:0];
myModalWindowViewController.delegate = self;
我不知道當您選擇嵌入到NavigationController中的ViewController時,DestinationViewController是NavigationController而不是ViewController。 我的錯!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.