![](/img/trans.png)
[英]presentModalViewController memory leak or EXC_BAD_ACCESS
[英]If I get EXC_BAD_ACCESS when accessing my view from a delegate, does that mean I have a memory leak?
我有一個這樣初始化的對象:
pdtd = [[ProfileDataTableDelegate alloc] initWithTableView:profileDataTableView scrollView:contentScrollView];
所以我的view
被傳遞給了pdtd
對象。 此時,我可以順利退出我的視圖 。 當我在文本字段內單擊並告訴滾動視圖重新定位時, 出現錯誤 。 在我的表委托(pdtd)上,出現此函數的第一行中出現錯誤“ EXC_BAD_ACCESS”的錯誤:
- (void)keyboardDidShow:(NSNotification *)notif {
[self.scrollView setContentOffset:CGPointMake(0, 100) animated:YES]; // <-- ERROR SHOWS UP HERE
[self.scrollView setContentSize:CGSizeMake([self.scrollView frame].size.width,
[self.scrollView frame].size.height + 100)];
}
這很奇怪,因為我正在另一種視圖上執行此操作,並且效果很好。 我不確定出什么問題或如何從調試器中獲取更多信息。 以下是相關類中的相關功能。
...
#import "ProfileDataTableDelegate.h"
@interface ProfileViewController : UIViewController <UINavigationControllerDelegate> {
UITableView *profileDataTableView;
ProfileDataTableDelegate *pdtd;
UINavigationBar *navBar;
UIScrollView *contentScrollView;
}
...
@property (nonatomic, retain) IBOutlet UITableView *profileDataTableView;
@property (nonatomic, retain) ProfileDataTableDelegate *pdtd;
@property (nonatomic, retain) IBOutlet UINavigationBar *navBar;
@property (nonatomic, retain) IBOutlet UIScrollView *contentScrollView;
@end
...
- (void)viewDidLoad {
[super viewDidLoad];
//nav title
[navBar.topItem setTitle:@"Your Profile"];
[self.navigationController setNavigationBarHidden:NO];
// nav bar button
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(saveBtnTouched:)];
saveButton.enabled = false;
[navBar.topItem setRightBarButtonItem:saveButton];
pdtd = [[ProfileDataTableDelegate alloc] initWithTableView:profileDataTableView scrollView:contentScrollView];
void (^block)(BOOL) = ^(BOOL is_valid) {
if(is_valid == YES) {
[saveButton setEnabled:YES];
} else if(is_valid == NO) {
[saveButton setEnabled:NO];
}
};
[pdtd setValidatorBlock:block];
}
...
...
#import "ValidatedTextViewTableCell.h"
typedef void (^ ValidatorBlock)(BOOL);
@interface ProfileDataTableDelegate : NSObject <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate> {
UITableView *profileDataTableView;
UIScrollView *scrollView;
...
}
- (id)initWithTableView:(UITableView *)tableView scrollView:(UIScrollView *)scrollView;
...
@property (nonatomic, retain) IBOutlet UITableView *profileDataTableView;
@property (nonatomic, retain) UIScrollView *scrollView;
@end
...
@implementation ProfileDataTableDelegate
@synthesize profileDataTableView;
@synthesize profileDataTableLabels;
@synthesize scrollView;
@synthesize emailCell, phoneCell, nameCell;
@synthesize validatedTextViewTableCell;
@synthesize validatorBlock;
- (id)initWithTableView:(UITableView *)tableView scrollView:(UIScrollView *)view {
self = [super init];
if(self) {
profileDataTableView = tableView;
[profileDataTableView setDelegate:self];
[profileDataTableView setDataSource:self];
scrollView = view;
profileDataTableLabels = [[NSArray alloc] initWithObjects:@"Name", @"Email", @"Phone", nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector (keyboardDidShow:)
name: UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector (keyboardDidHide:)
name: UIKeyboardDidHideNotification object:nil];
}
return self;
}
...
- (void)keyboardDidShow:(NSNotification *)notif {
//NSLog(@"keyboard did show %@", notif); // notif gives coordinates etc
//[scrollView setContentOffset:CGPointMake(0, 480 - 372) animated:YES];
[self.scrollView setContentOffset:CGPointMake(0, 100) animated:YES];
[self.scrollView setContentSize:CGSizeMake([self.scrollView frame].size.width,
[self.scrollView frame].size.height + 100)];
//[scrollView setFrame:CGRectMake(0, 0, 320, 320)];
// disable scrolling because it resets the rect position
//[scrollView setScrollEnabled:NO];
}
...
@end
我不確定如何獲取堆棧跟蹤信息(Xcode 4.2)。 同樣,在分析時有一些警告,但沒有嚴重的警告(例如藍色)。
您需要在ProfileDateTableDelegate.m
initWithTableView:
方法中調用self.scrollView = view
或scrollView = [view retain]
。
基本上發生的是,您的scrollView在可以訪問它之前已在其他視圖中釋放,因為即使您在屬性上指定了nonatomic,retain
,“委托”類也不以任何方式保留它。 由於您是直接在init
中設置ivar,而不是使用setter屬性,因此不會在其上調用keep。 當直接使用實例變量,你必須調用retain
,如果你想保留它自己。
避免此錯誤的一種方法是在ivar之前或之后使用下划線_
(Apple使用before,因此我使用after來避免私有ivar沖突),如下所示:
在.h中:
@interface{
UIScrollView *scrollView_;
}
@property (nonatomic,retain) UIScrollView *scrollView;
在* .m中:
@synthesize scrollView = scrollView_;
然后,您在init
,可以保留進入的視圖,如下所示:
scrollView_ = [view retain];
只要確保您在dealloc
正確釋放它即可:
- (void)dealloc{
[scrollView_ release], scrollView_ = nil;
[super dealloc];
}
您可以在此處找到有關所有這些的更多信息。
啊,可怕的EXC_BAD_ACCESS
。 在不閱讀所有代碼的情況下,這里有個提示,可以幫助您立即入門。 運行分析器。 然后,使用儀器中的“泄漏”工具。
有關詳細信息,以及有關導致這些錯誤的原因的出色鏈接以及有關如何修復的逐步說明,請查看以下問題的答案:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.