每当我尝试在UITableViewCell点击

时间:2016-07-24 20:28:30

标签: ios objective-c

我的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];
}

1 个答案:

答案 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图像资源,并将其设置为导航栏项。

我知道这是一个愚蠢的答案,但我希望有人可以从中获得帮助。