Objective-C 属性释放错误
是什么导致了这次崩溃?从我读到的所有内容来看,我正确使用了该属性。当我第一次调用方法 loadDot2Dot 时,它工作正常。然后,当我返回主菜单(调用 loadMainMenu)并尝试再次加载 dot2DotVC(再次调用 loadDot2DotVC)时,我遇到崩溃(Exc_Bad_Access) - 没有进一步的信息。
当我注释掉 [d2d release]; loadDot2Dot 中的行工作正常。我做错了什么吗?我知道我应该在那里发布...
干杯,
这是 .h
#import <UIKit/UIKit.h>
@class MenuVC;
@class Dot2DotVC;
@interface MyViewController : UIViewController {
UIViewController *menuVC;
UIViewController *dot2DotVC;
}
@property (nonatomic, retain) UIViewController *menuVC;
@property (nonatomic, retain) UIViewController *dot2DotVC;
- (IBAction)loadMainMenu:(id)sender;
- (IBAction)loadDot2Dot:(id)sender;
@end
这是 .m
#import "MyViewController.h"
#import "MenuVC.h"
#import "Dot2DotVC.h"
@implementation MyViewController
@synthesize dot2DotVC;
@synthesize menuVC;
- (IBAction)loadMainMenu:(id)sender {
if(self.menuVC != nil){
[self.menuVC.view removeFromSuperview];
}
MenuVC *menuController = [[MenuVC alloc] initWithNibName:@"iPadMenuVC" bundle:nil];
self.menuVC = menuController;
[menuController release];
[self.view insertSubview:self.menuVC.view atIndex:0];
if (self.dot2DotVC != nil) {
[self.dot2DotVC.view removeFromSuperview];
}
}
- (IBAction)loadDot2Dot:(id)sender {
Dot2DotVC *dvc = [[Dot2DotVC alloc] initWithNibName:@"iPadDot2DotVC" bundle:nil];
self.dot2DotVC = dvc;
[dvc release]; // If I comment out this release call, I don't get a crash.
[self.view insertSubview:dot2DotVC.view atIndex:0];
if (self.menuVC != nil) {
[self.menuVC.view removeFromSuperview];
}
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
MenuVC *menuController = [[MenuVC alloc] initWithNibName:@"iPadMenuVC" bundle:nil];
self.menuVC = menuController;
[menuController release];
[self.view insertSubview:self.menuVC.view atIndex:0];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
self.menuVC = nil;
self.dot2DotVC = nil;
[super dealloc];
}
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(void)viewDidAppear:(BOOL)animated {
[self becomeFirstResponder];
}
@end
ator/Documents/Princess_Pets/main.m:14
Program received signal: “EXC_BAD_ACCESS”. (gdb) bt
#0 0x30fb15fa in objc_msgSend ()
#1 0x314b9aca in CFRelease ()
#2 0x31525b58 in __CFTypeCollectionRelease ()
#3 0x31503522 in __CFArrayReleaseValues ()
#4 0x315038a2 in __CFArrayDeallocate ()
#5 0x314b9bc0 in _CFRelease ()
#6 0x314b9a9a in CFRelease ()
#7 0x30338038 in -[NSCFArray release] ()
#8 0x30fb29e8 in objc_setProperty ()
#9 0x0000f246 in -[Dot2DotVC setCurrentImages:] (self=0x13a310,
_cmd=0x19a8c, newArray=0x0) at /Users/adminstrator/Documents/Princess_Pets/Classes/Dot2DotVC.m:42
#10 0x0000ec36 in -[Dot2DotVC dealloc] (self=0x13a310, _cmd=0x33005660) at /Users/adminstrator/Documents/Princess_Pets/Classes/Dot2DotVC.m:1474
#11 0x314ba71a in -[NSObject release] ()
#12 0x30fb29e8 in objc_setProperty ()
#13 0x00004452 in -[Princess_PetsViewController setDot2DotVC:] (self=0x11d800,
_cmd=0x194f9, _value=0x145100) at /Users/adminstrator/Documents/Princess_Pets/Classes/Princess_PetsViewController.m:20
#14 0x00003234 in -[Princess_PetsViewController loadDot2Dot:] (self=0x11d800,
_cmd=0x1962e, sender=0x146840) at /Users/adminstrator/Documents/Princess_Pets/Classes/Princess_PetsViewController.m:107
#15 0x314db16c in -[NSObject performSelector:withObject:withObject:] ()
#16 0x322930d4 in -[UIApplication sendAction:to:from:forEvent:] ()
#17 0x32293074 in -[UIApplication sendAction:toTarget:fromSender:forEvent:] ()
#18 0x32293046 in -[UIControl sendAction:to:forEvent:] ()
#19 0x32292d98 in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#20 0x322933e6 in -[UIControl touchesEnded:withEvent:] ()
#21 0x32291dbc in -[UIWindow _sendTouchesForEvent:] ()
#22 0x32291704 in -[UIWindow sendEvent:] ()
#23 0x3228d326 in -[UIApplication sendEvent:] ()
#24 0x3228cc92 in _UIApplicationHandleEvent ()
#25 0x3414eb32 in PurpleEventCallback ()
#26 0x314d8d9c in CFRunLoopRunSpecific ()
#27 0x314d84e0 in CFRunLoopRunInMode ()
#28 0x3414e0da in GSEventRunModal ()
#29 0x3414e186 in GSEventRun ()
#30 0x32241430 in -[UIApplication _run] ()
#31 0x3223f95a in UIApplicationMain ()
#32 0x00002852 in main (argc=1, argv=0x2ffff60c) at /Users/adminstrator/Documents/Princess_Pets/main.m:14ator/Documents/Princess_Pets/main.m:14
what could be causing this crash? From everything I've read, I'm using the property correctly. When I call the method loadDot2Dot a first time, it works fine. Then when I go back to the main menu (call loadMainMenu) and try to load the dot2DotVC again (call loadDot2DotVC again), I get a crash (Exc_Bad_Access) - with no further info.
When I comment out the [d2d release]; line in loadDot2Dot it works fine. Am I doing something wrong? I know I should be releasing there...
Cheers,
Here's the .h
#import <UIKit/UIKit.h>
@class MenuVC;
@class Dot2DotVC;
@interface MyViewController : UIViewController {
UIViewController *menuVC;
UIViewController *dot2DotVC;
}
@property (nonatomic, retain) UIViewController *menuVC;
@property (nonatomic, retain) UIViewController *dot2DotVC;
- (IBAction)loadMainMenu:(id)sender;
- (IBAction)loadDot2Dot:(id)sender;
@end
Here's the .m
#import "MyViewController.h"
#import "MenuVC.h"
#import "Dot2DotVC.h"
@implementation MyViewController
@synthesize dot2DotVC;
@synthesize menuVC;
- (IBAction)loadMainMenu:(id)sender {
if(self.menuVC != nil){
[self.menuVC.view removeFromSuperview];
}
MenuVC *menuController = [[MenuVC alloc] initWithNibName:@"iPadMenuVC" bundle:nil];
self.menuVC = menuController;
[menuController release];
[self.view insertSubview:self.menuVC.view atIndex:0];
if (self.dot2DotVC != nil) {
[self.dot2DotVC.view removeFromSuperview];
}
}
- (IBAction)loadDot2Dot:(id)sender {
Dot2DotVC *dvc = [[Dot2DotVC alloc] initWithNibName:@"iPadDot2DotVC" bundle:nil];
self.dot2DotVC = dvc;
[dvc release]; // If I comment out this release call, I don't get a crash.
[self.view insertSubview:dot2DotVC.view atIndex:0];
if (self.menuVC != nil) {
[self.menuVC.view removeFromSuperview];
}
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
MenuVC *menuController = [[MenuVC alloc] initWithNibName:@"iPadMenuVC" bundle:nil];
self.menuVC = menuController;
[menuController release];
[self.view insertSubview:self.menuVC.view atIndex:0];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
self.menuVC = nil;
self.dot2DotVC = nil;
[super dealloc];
}
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(void)viewDidAppear:(BOOL)animated {
[self becomeFirstResponder];
}
@end
ator/Documents/Princess_Pets/main.m:14
Program received signal: “EXC_BAD_ACCESS”. (gdb) bt
#0 0x30fb15fa in objc_msgSend ()
#1 0x314b9aca in CFRelease ()
#2 0x31525b58 in __CFTypeCollectionRelease ()
#3 0x31503522 in __CFArrayReleaseValues ()
#4 0x315038a2 in __CFArrayDeallocate ()
#5 0x314b9bc0 in _CFRelease ()
#6 0x314b9a9a in CFRelease ()
#7 0x30338038 in -[NSCFArray release] ()
#8 0x30fb29e8 in objc_setProperty ()
#9 0x0000f246 in -[Dot2DotVC setCurrentImages:] (self=0x13a310,
_cmd=0x19a8c, newArray=0x0) at /Users/adminstrator/Documents/Princess_Pets/Classes/Dot2DotVC.m:42
#10 0x0000ec36 in -[Dot2DotVC dealloc] (self=0x13a310, _cmd=0x33005660) at /Users/adminstrator/Documents/Princess_Pets/Classes/Dot2DotVC.m:1474
#11 0x314ba71a in -[NSObject release] ()
#12 0x30fb29e8 in objc_setProperty ()
#13 0x00004452 in -[Princess_PetsViewController setDot2DotVC:] (self=0x11d800,
_cmd=0x194f9, _value=0x145100) at /Users/adminstrator/Documents/Princess_Pets/Classes/Princess_PetsViewController.m:20
#14 0x00003234 in -[Princess_PetsViewController loadDot2Dot:] (self=0x11d800,
_cmd=0x1962e, sender=0x146840) at /Users/adminstrator/Documents/Princess_Pets/Classes/Princess_PetsViewController.m:107
#15 0x314db16c in -[NSObject performSelector:withObject:withObject:] ()
#16 0x322930d4 in -[UIApplication sendAction:to:from:forEvent:] ()
#17 0x32293074 in -[UIApplication sendAction:toTarget:fromSender:forEvent:] ()
#18 0x32293046 in -[UIControl sendAction:to:forEvent:] ()
#19 0x32292d98 in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#20 0x322933e6 in -[UIControl touchesEnded:withEvent:] ()
#21 0x32291dbc in -[UIWindow _sendTouchesForEvent:] ()
#22 0x32291704 in -[UIWindow sendEvent:] ()
#23 0x3228d326 in -[UIApplication sendEvent:] ()
#24 0x3228cc92 in _UIApplicationHandleEvent ()
#25 0x3414eb32 in PurpleEventCallback ()
#26 0x314d8d9c in CFRunLoopRunSpecific ()
#27 0x314d84e0 in CFRunLoopRunInMode ()
#28 0x3414e0da in GSEventRunModal ()
#29 0x3414e186 in GSEventRun ()
#30 0x32241430 in -[UIApplication _run] ()
#31 0x3223f95a in UIApplicationMain ()
#32 0x00002852 in main (argc=1, argv=0x2ffff60c) at /Users/adminstrator/Documents/Princess_Pets/main.m:14ator/Documents/Princess_Pets/main.m:14
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从回溯来看,您的问题似乎直接出现在 Dot2DotVC 中。在其 -dealloc 中,它在 self 上调用 -setCurrentImages: ,这会释放旧值,该值似乎包含垃圾对象。换句话说,当在视图控制器上调用 -dealloc 时,Dot2DotVC 上的数组属性
currentImages
至少包含一个无效对象。作为旁注,我强烈建议您不要在 -dealloc 中使用属性访问。您在问题中列出的 -dealloc 会更好,因为:
这可以避免被覆盖的设置器或挥之不去的 KVO 观察者的任何潜在问题。
From the backtrace, your problem appears to be in Dot2DotVC directly. In its -dealloc, it's calling -setCurrentImages: on self, which releases the old value, which appears to be containing a garbage object. In other words, the array property
currentImages
on your Dot2DotVC contains at least one invalid object by the time -dealloc is called on the view controller.As a side note, I strongly encourage you to not use property access in -dealloc. The -dealloc you have listed in your question would be better off as:
This avoids any potential issues with overridden setters or lingering KVO observers.