我的iOS应用程序以前一直运行良好,但是每当我点击表格单元格并尝试推送另一个视图控制器时,它突然崩溃。
在做了大量的研究后,我明白这是因为在推动发生之前销毁了,但是我无法弄清楚在哪里以及为什么。
该应用程序是一个用Objective-C编写并使用非ARC模式的旧项目。
错误消息在每次崩溃时都不清楚,因此我尝试将animated
标记设置为NO
pushViewController
的{{1}},现在我得到了EXC_BAD_ACCESS
每一次。
如何缩小错误的位置并修复这个烦人的错误?
更新:还有一条信息。对于具有 xib
个文件的其他视图控制器,它们将被成功推送。这仅发生在由代码生成的视图控制器上。
以下是推送视图控制器的代码段:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath* pagePath = [[self.pageIndexPath indexPathByAddingIndex:indexPath.section] indexPathByAddingIndex:indexPath.row];
NSString *viewController = [[ContentStore contentStore] viewControllerForPage:pagePath];
if (viewController) {
NSString *title = [[ContentStore contentStore] titleForPage:pagePath];
UIViewController *testVC = [[NSClassFromString(viewController) alloc] init];
testVC.navigationItem.title = title;
NSLog(@"%@", self.parentVC.navigationController.viewControllers);
[self.parentVC.navigationController pushViewController:testVC animated:NO];
} else {
NSString *remoteUrl = [[ContentStore contentStore] remoteURLForPage:pagePath];
DownloadManager *manager = [DownloadManager sharedManager];
if ( remoteUrl && ( ![manager isRemoteResourceMarkedForDownload:remoteUrl] || ![manager isRemoteResourceDownloaded:remoteUrl] ) ) {
[[DownloadManager sharedManager] markRemoteResource:remoteUrl forDownload:YES];
[[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadTables" object:nil];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:@"ChangePage"
object:nil
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:pagePath,@"ChangePage",
@"YES", @"Animate",@"YES",@"Remapped",@"NO",@"Sandbox",nil]];
}
}
}
在上面的代码片段中,if (viewController)
子句不会也会导致崩溃(相应的视图控制器xib
和类存在)。
这是changePage
中的AppDelegate
通知处理程序:
- (void)changePage:(NSNotification*)notification {
NSIndexPath* pathIndex = [[notification userInfo] objectForKey:@"ChangePage"];
NSString* shortcut = [[notification userInfo] objectForKey:@"Shortcut"];
bool animate = [[[notification userInfo] objectForKey:@"Animate"] boolValue];
bool sandbox = [[[notification userInfo] objectForKey:@"Sandbox"] boolValue];
//bool remapped = [[[notification userInfo] objectForKey:@"Remapped"] boolValue];
NSString* words = [[notification userInfo] objectForKey:@"Words"];
//NSLog(@"changePage: %@ animate=%d sandbox=%d ", pathIndex,animate,sandbox );
if ( pathIndex.length==0 ) {
pathIndex = [[ContentStore contentStore] pathIndexForShortcutId:shortcut];
if ( pathIndex.length==0 ) {
pathIndex = [NSIndexPath indexPathWithIndex:0];
}
}
[Flurry logEvent:@"ChangePage" withParameters:[NSDictionary dictionaryWithObject:pathIndex forKey:@"Path"]];
NSUInteger selectedTab = [pathIndex indexAtPosition:0];
UINavigationController* nvc = nil;
if ( self.tabBarController.viewControllers.count>selectedTab )
nvc = [self.tabBarController.viewControllers objectAtIndex:selectedTab];
if ( !nvc ) return; // Exit for non-existing tabs.
NSMutableArray *stack =[NSMutableArray arrayWithArray:nvc.viewControllers];
// Pop viewcontrollers until pathIndex has a partial match.
while(true) {
BaseViewController* last = [stack lastObject];
if (!last) break;
if ( pathIndex.length < last.pageIndexPath.length ) {
[stack removeLastObject];
} else {
bool match = YES;
for(NSUInteger position=0;position<last.pageIndexPath.length;position++) {
if ( [pathIndex indexAtPosition:position] != [last.pageIndexPath indexAtPosition:position] ) {
match = NO;
break;
}
}
if (match) {
break;
} else {
[stack removeLastObject];
}
}
}
for(NSUInteger position=((BaseViewController*)[stack lastObject]).pageIndexPath.length;position+1<pathIndex.length;position+=2) {
BaseViewController* last = [stack lastObject];
NSIndexPath* newPageIndex = [[last.pageIndexPath indexPathByAddingIndex:[pathIndex indexAtPosition:position]] indexPathByAddingIndex:[pathIndex indexAtPosition:position+1]];
BaseViewController* newVC = [self createViewControllerWithPageIndexPath:newPageIndex parentViewController:[stack lastObject]];
if ( [newVC isKindOfClass:WebViewController.class] ) {
[(WebViewController*)newVC setSandboxed:sandbox];
[(WebViewController*)newVC setWords:words];
}
if ( !newVC ) break; // Fail in path, stop
[stack addObject:newVC];
}
// Set the stack
[nvc setViewControllers:stack animated:animate];
[self.tabBarController setSelectedIndex:selectedTab];
[self showDisclaimer];
}
答案 0 :(得分:0)
我终于解决了这个问题。
我启用了僵尸并发现了错误消息 - [UIImage retain]: message sent to deallocated instance
,因此我开始查看可能存在内存管理不善的代码,并找到导致问题的行:
在RootViewController.m
(所有视图控制器都是继承自的)中,
- (void)viewDidAppear:(BOOL)animated {
...
/* Search button on the nav bar */
UIImage *image = [[UIImage imageNamed:@"ui_tabbar_search.png"] autorelease];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(searchButtonClicked:)];
}
所以我是autoreleasing
图像资源,并将其设置为导航栏项。
我知道这是一个愚蠢的答案,但我希望有人可以从中获得帮助。