【发布时间】:2013-10-05 01:09:52
【问题描述】:
我已经开发一个应用程序大约一个星期了,我认为现在是分析它以确保我做的一切正确的好时机,我发现即使我所有的对象都在解除分配的分配量正在增加。当我释放一个对象时,我会执行以下操作:
[object release];
object = nil;
在我的应用程序中,我有一个初始视图控制器,它决定显示我的LoginViewController 或TimeLineViewController,具体取决于我是否有访问令牌。 (这部分无关紧要,因为我遇到的问题在LoginViewController/SignupViewController.)。登录控制器有两个文本字段和两个按钮,这些按钮要么将 sVC 推送到导航视图控制器上,要么尝试登录。
奇怪的是,dealloc 方法正在我的视图和视图控制器上被调用,但在调用它们之后内存却增加了。
SDK 版本 7.0 Xcode 5.0版
编辑:
在我的 LoginViewController 中,当我从 LoginView 中收到 SignupButton 已被单击的事件时,将调用此方法:
- (void)signupButtonPressed
{
SignupViewController *signupVC = [[SignupViewController alloc] init];
[self.navigationController pushViewController:signupVC animated:true];
destroy(signupVC);
}
***注意,destroy宏如下:
#define destroy($x) \
if($x) \
{ \
[$x release]; \
$x = nil; \
}
SignupViewController创建时ViewDidLoad方法如下:
self.view = [[SignupView alloc] initWithFrame:self.view.frame];
[[(SignupView *)self.view evtSignupButtonPressed] addHandler:AFFHandler(@selector(signupPressed))];
[((SignupView *)self.view).profileImage addTarget:self action:@selector(profileImagePressed) forControlEvents:UIControlEventTouchUpInside];
[self.navigationController setNavigationBarHidden:false animated:true];
然后它为 SignupView 中的视图创建 UI,如下所示:
- (void)setupUI
{
self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:IS_IPHONE5 ? @"genericBackground-568h.jpg" : @"genericBackground.jpg"]];
_overlayView = [[UIView alloc] initWithFrame:self.frame];
_scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
_profileImage = [[UIButton alloc] init];
profileImageContainer = [[UIView alloc] initWithFrame:CGRectMake(18.5, 0, _profileImage.imageView.image.size.width + 10, _profileImage.imageView.image.size.height + 10)];
selectProfilePictureText = [[UILabel alloc] initWithFrame:CGRectMake(profileImageContainer.affX, 0, 229, 17)];
UIView *padding = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 17, 40)];
_usernameField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 284, 40)];
_usernameField.delegate = self;
_passwordField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 284, 40)];
_passwordField.delegate = self;
_repeatPasswordField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 284, 40)];
_repeatPasswordField.delegate = self;
_emailField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 284, 40)];
_emailField.delegate = self;
destroy(padding);
buttonImage = [[UIImage imageNamed:@"largeButton.png"] copy];
_submitButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height)];
[_submitButton addTarget:self action:@selector(signupButtonPressed) forControlEvents:UIControlEventTouchUpInside];
destroy(buttonImage);
[self addSubview:_scrollView];
[self addSubview:_overlayView];
[_scrollView addSubview:profileImageContainer];
[profileImageContainer addSubview:_profileImage];
[_scrollView addSubview:selectProfilePictureText];
[_scrollView addSubview:_usernameField];
[_scrollView addSubview:_passwordField];
[_scrollView addSubview:_repeatPasswordField];
[_scrollView addSubview:_emailField];
[_scrollView addSubview:_submitButton];
destroy(profileImageContainer);
destroy(selectProfilePictureText);
}
**注意,我省略了所有更改这些对象属性的代码,例如更改背景颜色等。
SignupVC和SignupView的dealloc方法如下:
注册视图:
- (void)dealloc
{
self.usernameField.delegate = nil;
self.passwordField.delegate = nil;
self.repeatPasswordField.delegate = nil;
self.emailField.delegate = nil;
AFFRemoveAllEvents();
destroyAndRemove(_usernameField);
destroyAndRemove(_passwordField);
destroyAndRemove(_repeatPasswordField);
destroyAndRemove(_emailField);
destroyAndRemove(_profileImage);
destroyAndRemove(_submitButton);
destroyAndRemove(_scrollView);
destroyAndRemove(_overlayView);
if(buttonImage)
destroy(buttonImage);
[super dealloc];
}
SignupVC(在 NavigationBar 的后退按钮被按下后调用)
- (void)dealloc
{
[[(SignupView *)self.view evtSignupButtonPressed] removeHandlersForObserver:self];
[((SignupView *)self.view).profileImage removeTarget:self action:@selector(profileImagePressed) forControlEvents:UIControlEventTouchUpInside];
destroy(profileImage);
destroyAndRemove(self.view);
[super dealloc];
}
DestroyAndRemove 这样做:
#define destroyAndRemove($x) \
if($x) \
{ \
[$x removeFromSuperview]; \
[$x release]; \
$x = nil; \
}
【问题讨论】:
-
您在哪种乐器中看到了这个?
-
您选择在不使用ARC 的情况下开发现代iOS 应用程序有什么原因吗?
-
那个destroy宏有点奇怪。
-
祈祷告诉
destroyAndRemove做什么?以及为什么需要如此复杂的发布方案——只需执行[ptrName release]就足够了,尽管你可以根据需要将其设置为 nil——不需要if测试。 -
@HotLicks,我同意-
if测试简直是浪费。 @ApperleyA,请考虑:1) 对象已被released设置为nil,if语句将crash应用程序或 2) 对象已设置为 @987654343 @,在nil上调用任何方法都不会做任何事情。 ->if检查对象是否已释放的语句是不好的做法。
标签: ios objective-c cocoa-touch memory-management ios7