好吧所以我试图在Xcode中使用一个简单的UINavigationController和iPhone SDK,它在推送时效果很好但是如果经过2次推送并尝试弹出视图控制器我会不断收到错误:EXC_BAD_ACCESS
我知道这意味着什么,但我该怎么办呢?
这是我的代码...(假设MainViewController有一个调用函数showStartMenu的按钮)
// // FurballAppDelegate.h // Furball // // Created by Morgan Family on 7/28/10. // Copyright __MyCompanyName__ 2010. All rights reserved. // #import <UIKit/UIKit.h> @class MainViewController, StartViewController, SubjectViewController; @interface FurballAppDelegate : NSObject <UIApplicationDelegate> { UIWindow *window; UINavigationController *navController; MainViewController *mainController; StartViewController *startController; } @property (nonatomic, retain) UIWindow *window; @property (nonatomic, retain) UINavigationController *navController; @property (nonatomic, retain) MainViewController *mainController; @property (nonatomic, retain) StartViewController *startController; - (void)popBack; - (void)pushNext:(UIViewController *)next; - (void)showStartMenu; @end
// // FurballAppDelegate.m // Furball // // Created by Morgan Family on 7/28/10. // Copyright __MyCompanyName__ 2010. All rights reserved. // #import "FurballAppDelegate.h" #import "MainViewController.h" #import "StartViewController.h" #import "SubjectViewController.h" @implementation FurballAppDelegate @synthesize window; @synthesize navController; @synthesize mainController; @synthesize startController; - (void)applicationDidFinishLaunching:(UIApplication *)application { window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; mainController = [[MainViewController alloc] init]; navController = [[UINavigationController alloc] initWithRootViewController:mainController]; [window addSubview:navController.view]; [window makeKeyAndVisible]; } - (void)dealloc { [mainController release]; [startController release]; [subjectController release]; [window release]; [super dealloc]; } - (void)popBack { [navController popViewControllerAnimated:YES]; } - (void)pushNext:(UIViewController *)next { [navController pushViewController:next animated:YES]; } - (void)showStartMenu { startController = [[StartViewController alloc] init]; [self pushNext:startController]; } @end
// // StartViewController.h // Furball // // Created by Morgan Family on 8/4/10. // Copyright 2010 __MyCompanyName__. All rights reserved. // #import @interface StartViewController : UIViewController { } - (void)showSubjectMenu; @end
// // StartViewController.m // Furball // // Created by Morgan Family on 8/4/10. // Copyright 2010 __MyCompanyName__. All rights reserved. // #import "FurballAppDelegate.h" #import "StartViewController.h" #import "SubjectViewController.h" @implementation StartViewController - (void)loadView { UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame]; UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [btn setFrame:CGRectMake(50, 50, 100, 30)]; [btn setTitle:@"DO WORK" forState:UIControlStateNormal]; [btn addTarget:self action:@selector(chooseSubject) forControlEvents:UIControlEventTouchUpInside]; [view addSubview:btn]; FurballAppDelegate *app = [[UIApplication sharedApplication] delegate]; UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [btnBack setFrame:CGRectMake(50, 100, 100, 30)]; [btnBack setTitle:@"DO WORK" forState:UIControlStateNormal]; [btnBack addTarget:app action:@selector(popBack) forControlEvents:UIControlEventTouchUpInside]; [view addSubview:btnBack]; self.view = view; [view release]; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)chooseSubject { FurballAppDelegate *app = [[UIApplication sharedApplication] delegate]; SubjectViewController *subjectController = [[SubjectViewController alloc] init]; [app pushNext:subjectController]; } - (void)dealloc { [super dealloc]; } @end
所有推送我的所有文件都有效。当我触摸它时,即使是“btnBack”,也会将导航控制器弹回到MainViewController ...但是当我创建一个与StartViewController上的按钮相同的后退按钮时,在SubjectViewController上它会给我一个奇怪的错误。
我非常感谢任何帮助:)
答案 0 :(得分:3)
由于您意识到这意味着您正在尝试访问无效的内存地址,因此您需要检查代码是否存在无效的内存访问。
幸运的是,对于此错误,它通常位于您收到EXEC_BAD_ACCESS的行上。查看该行上的对象和指针。它们都有意义吗?如果没有,请备份一条线。洗涤,冲洗并重复。在某个地方,你没有正确地分配一个对象,过早发布它,堆栈损坏,或者某些变量指向随机垃圾。
在收到错误的地方发布一些代码可能会让我们发现错误。但是,如果不能在调试器中单步执行,也可能无法看到。
答案 1 :(得分:1)
弹出视图控制器时获取EXEC_BAD_ACCESS会让我怀疑在视图控制器中的dealloc方法中触发了错误。释放一个对象两次,或释放一个自动释放的对象?
答案 2 :(得分:0)
我没有具体找到我在哪里遇到内存问题,但我使用了另一种方法,创建了我自己的导航控制器类,扩展了UIViewController类,它对我正在使用的应用程序工作得更好。它使用非常少的内存,但按类名记忆控制器,因此添加所有UIViewControllers都不起作用。但这不是我想要的。我有很多视图控制器都有不同的类名,这很好用:)
// // FurballNavigationController.h // Furball // #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @class UIViewController; @protocol FurballNavigationDelegate; @interface FurballNavigationController : UIViewController <FurballNavigationDelegate> { NSMutableArray *viewControllers; int currentController; UIViewController *pendingView; int pendingDirection; } @property (nonatomic, retain) NSMutableArray *viewControllers; @property (nonatomic) int currentController; - (id)initWithRootViewController:(UIViewController *)viewController; - (id)initWithViewControllers:(NSArray *)controllers; - (void)addObject:(id)object; - (void)removeObject:(unsigned int)index; - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)yesOrNo; - (UIViewController *)popViewControllerAnimated:(BOOL)yesOrNo; - (void)popToRootViewControllerAnimated:(BOOL)yesOrNo; - (void)animateSlide:(UIViewController *)viewController direction:(NSString * const)direction; @end @protocol FurballNavigationDelegate @optional - (void)viewFinishedAnimation; - (void)viewShouldPush:(UIViewController *)viewController; - (void)viewWillPush:(UIViewController *)viewController; - (void)viewDidPush:(UIViewController *)viewController; - (UIViewController *)viewShouldPopAnimated:(BOOL)yesOrNo; - (UIViewController *)viewWillPopAnimated:(BOOL)yesOrNo; - (UIViewController *)viewDidPopAnimated:(BOOL)yesOrNo; @end
// // FurballNavigationController.m // Furball // #import "FurballNavigationController.h" @implementation FurballNavigationController @synthesize viewControllers; @synthesize currentController; - (id)init { NSMutableArray *arr = [[NSMutableArray alloc] init]; self.viewControllers = arr; [arr release]; currentController = 0; pendingView = nil; pendingDirection = 0; return self; } - (id)initWithRootViewController:(UIViewController *)viewController { if(self = [self init]) { if(viewController == nil) { viewController = [[UIViewController alloc] init]; viewController.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame]; [viewController.view setBackgroundColor:[UIColor redColor]]; } [self addObject:viewController]; self.view = viewController.view; } return self; } - (id)initWithViewControllers:(NSArray *)controllers { if(self = [self initWithViewControllers:[controllers objectAtIndex:0]]) { viewControllers = (NSMutableArray *)controllers; } return self; } - (void)addObject:(id)object { [viewControllers addObject:[NSString stringWithFormat:@"%@", [object class]]]; } - (void)removeObject:(unsigned int)index { [viewControllers removeObjectAtIndex:(NSInteger)index]; } - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)yesOrNo { pendingView = viewController; pendingDirection = 1; yesOrNo ? [self animateSlide:viewController direction:kCATransitionFromRight] : [self viewFinishedAnimation]; } - (UIViewController *)popViewControllerAnimated:(BOOL)yesOrNo { UIViewController *controller = [[NSClassFromString([viewControllers objectAtIndex:currentController-1]) alloc] init]; pendingView = controller; pendingDirection = -1; yesOrNo ? [self animateSlide:controller direction:kCATransitionFromLeft] : [self viewFinishedAnimation]; return controller; } - (void)popToRootViewControllerAnimated:(BOOL)yesOrNo { UIViewController *controller = [[NSClassFromString([viewControllers objectAtIndex:0]) alloc] init]; pendingView = controller; pendingDirection = -2; yesOrNo ? [self animateSlide:controller direction:kCATransitionFromLeft] : [self viewFinishedAnimation]; } - (void)animateSlide:(UIViewController *)viewController direction:(NSString * const)direction { UIView *currentView = self.view; UIView *theWindow = [currentView superview]; UIView *newView = viewController.view; [currentView removeFromSuperview]; [theWindow addSubview:newView]; CATransition *animation = [CATransition animation]; [animation setDuration:0.5]; [animation setType:kCATransitionPush]; [animation setSubtype:direction]; [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [[theWindow layer] addAnimation:animation forKey:@"SwitchToView1"]; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(viewFinishedAnimation) userInfo:nil repeats:NO]; timer; } - (void)viewFinishedAnimation { self.view = pendingView.view; if(pendingDirection > 0) { [self addObject:pendingView]; currentController++; } else if(pendingDirection == -1) { [self removeObject:currentController]; currentController--; } else if(pendingDirection == -2) { for(int i = 1; i < [viewControllers count]; i++) [self removeObject:i]; currentController = 0; } } - (void)viewShouldPush:(UIViewController *)viewController { } - (void)viewWillPush:(UIViewController *)viewController { } - (void)viewDidPush:(UIViewController *)viewController { } - (UIViewController *)viewShouldPopAnimated:(BOOL)yesOrNo { return [[UIViewController alloc] init]; } - (UIViewController *)viewWillPopAnimated:(BOOL)yesOrNo { return [[UIViewController alloc] init]; } - (UIViewController *)viewDidPopAnimated:(BOOL)yesOrNo { return [[UIViewController alloc] init]; } @end
感谢其他人的帮助:D