[英]'EXEC_BAD_ACCESS' in Table View, “[TasksPageViewController tableView:numberOfRowsInSection:]”
I've been trying to solve this bad reference for 2 days now, but I cannot find a fix. 我已经尝试解决这一错误的参考资料已有2天了,但是我找不到解决方法。
My application is a basic to-do list with several pages (UIPageControl) for different categories and a first page for statistics about the tasks the user has finished. 我的应用程序是一个基本的待办事项列表,其中包含用于不同类别的几页(UIPageControl),以及用于统计有关用户已完成任务的第一页。 (if you got 3 categories, you end up with 4 pages). (如果您有3个类别,则最终会有4页)。
It loads an array of categories from NSUserDefaults, which can be modified by a modal view accessed through a UIButton just like the (i) in the wheather app. 它从NSUserDefaults加载一系列类别,可以通过通过UIButton访问的模式视图修改该类别,就像Wheather应用中的(i)一样。
The Page Control is built by the ViewController
class, (which is the primary view). 页面控件由ViewController
类(它是主视图)构建。 For each element in the array of categories, the view controller generates a new TasksPageViewController
class instance and instantiates a storyboard view for it. 对于类别数组中的每个元素,视图控制器都会生成一个新的TasksPageViewController
类实例,并TasksPageViewController
实例化一个情节TasksPageViewController
视图。
Everything was working fine untill I put a UITableView
in the TasksPageViewController
view in storyboard and linked its dataSource to the same class. 一切工作正常,直到我将UITableView
放在情节TasksPageViewController
视图中并将其dataSource链接到同一类。
After implementing the required classes for the UITableView dataSource in the TasksPageViewController
, it runs fine, but if I try to go to the modal view for modifying the categories, when I press DONE (and it should reload the ViewController and rebuild the many pages for the UIPageControll), the application crashes with a EXEC_BAD_ACCESS. 在TasksPageViewController
为UITableView dataSource实现所需的类后,它可以正常运行,但是如果我尝试进入模态视图以修改类别,则在按DONE时(它应该重新加载ViewController并为该页面重新构建许多页面) UIPageControll),则应用程序将因EXEC_BAD_ACCESS而崩溃。
Debugging with NSZombiesEnabled, I got: 使用NSZombiesEnabled进行调试,我得到了:
2012-02-12 18:55:49.460 Pontinhos[25601:fe03] * -[TasksPageViewController tableView:numberOfRowsInSection:]: message sent to deallocated instance 0x68c3040 2012-02-12 18:55:49.460 Pontinhos [25601:fe03] * -[TasksPageViewController tableView:numberOfRowsInSection:]:已发送消息到已释放实例0x68c3040
But I don't really know how to proceed, I don't know which object that have been released I'm calling. 但是我真的不知道该如何进行,我不知道我正在调用哪个对象。
The scripts are the following: 脚本如下:
ViewController.h ViewController.h
#import <UIKit/UIKit.h>
#import "MainPageViewController.h"
#import "TasksPageViewController.h"
@interface ViewController : UIViewController{
IBOutlet UIScrollView *scrollView;
IBOutlet UIPageControl *pageControl;
NSMutableArray * views;
// To be used when scrolls originate from the UIPageControl
BOOL pageControlUsed;
}
@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
@property (nonatomic, retain) IBOutlet UIPageControl *pageControl;
@property (nonatomic, retain) NSMutableArray *views;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (IBAction)changePage;
@end
ViewController.m ViewController.m
#import "ViewController.h"
@implementation ViewController
@synthesize scrollView;
@synthesize pageControl;
@synthesize views;
//carrega views que estão na array.
- (void)viewDidLoad
{
[super viewDidLoad];
//LoadCategories
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
NSMutableArray *categories = [[NSMutableArray alloc] initWithArray:[data objectForKey:@"categories"]];
// MAIN PAGE
MainPageViewController *mainpage = [self.storyboard instantiateViewControllerWithIdentifier:@"MainPageViewController"];
CGRect mframe = scrollView.frame;
mframe.origin.x = 0;
mframe.origin.y = 0;
mainpage.view.frame = mframe;
[self.scrollView addSubview:mainpage.view];
int i = 1;
NSLog(@"Iniciando criação de páginas!");
for(id name in categories) {
NSLog(@"Carregou página.%i",i);
NSLog(@"categories count:%i",[categories count]);
TasksPageViewController *tasks = [self.storyboard instantiateViewControllerWithIdentifier:@"TasksPageViewController"];
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * i;
frame.origin.y = 0;
tasks.view.frame = frame;
[tasks populateWithData:(i-1) categoryName:name];
[scrollView addSubview:tasks.view];
tasks = nil;
i++;
}
self.pageControl.numberOfPages = [categories count]+1;
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * ([categories count]+1), self.scrollView.frame.size.height);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (pageControlUsed)
{
// do nothing - the scroll was initiated from the page control, not the user dragging
return;
}
// Update the page when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
- (IBAction)changePage {
// update the scroll view to the appropriate page
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * self.pageControl.currentPage;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
[self.scrollView scrollRectToVisible:frame animated:YES];
pageControlUsed = YES;
}
// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
pageControlUsed = NO;
}
// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
pageControlUsed = NO;
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.scrollView = nil;
}
@end
TasksPageViewController.h TasksPageViewController.h
#import <UIKit/UIKit.h>
#import "TasksTableCellPrototypes.h"
@interface TasksPageViewController : UIViewController <UITableViewDataSource>{
IBOutlet UILabel *categoryName;
IBOutlet UITableView *tableView;
//NSMutableArray *tasksData;
}
//@property (nonatomic,retain) NSMutableArray *tasksData;
@property (nonatomic,retain) UITableView *tableView;
@property (nonatomic,retain) UILabel *categoryName;
- (void) populateWithData:(int)dataId categoryName:(NSString *)name;
@end
TasksPageViewController.m TasksPageViewController.m
#import "TasksPageViewController.h"
@implementation TasksPageViewController
@synthesize tableView;
//@synthesize tasksData;
@synthesize categoryName;
- (void)viewDidLoad
{
[super viewDidLoad];
// NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
//tasksData = [[NSMutableArray alloc] initWithArray:[data objectForKey:@"tasks"]];
//tasksData = [[NSMutableArray alloc] initWithObjects:@"lalal",@"lololo",nil];
}
- (void) populateWithData:(int)dataId categoryName:(NSString *)name {
//self.categoryName.text = name;
}
// Número de categorias
- (NSInteger)tableView:(UITableView *)tableViewnumberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSLog(@"contou table view tasks");
return 4;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
TasksTableCellPrototypes *cell = [[TasksTableCellPrototypes alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"taskCell"];
return cell;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (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
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
Thank you. 谢谢。
EDIT: apparently The ViewController
isn't retaining the reference to the TasksPageViewController
and the UITableView
cannot find its dataSource. 编辑:显然ViewController
不会保留对TasksPageViewController
的引用,而UITableView
找不到其dataSource。 I don't really know how to retain this using ARC. 我真的不知道如何使用ARC保留它。
In your ViewController viewDidLoad
, when you loop through the categories you instantiate a TasksPageViewController named tasks
, but then you do not retain the reference anywhere. 在ViewController viewDidLoad
,当您遍历类别时,将实例化一个名为tasks
的TasksPageViewController,但是您不会在任何地方保留引用。 So later the TasksPageViewController cannot be found when the tableView:numberOfRowsInSection:
message is sent. 因此,稍后在发送tableView:numberOfRowsInSection:
消息时找不到TasksPageViewController。
I see that in your ViewController your synthesize a property named views
but then you do not use that property anywhere. 我看到在您的ViewController中,您合成了一个名为views
的属性,但是您在任何地方都不使用该属性。 Perhaps you should rename that property viewControllers
and then at the end of the loop in viewDidLoad
, you should add your tasks
object to the viewControllers
mutable array, instead of setting tasks
to nil. 也许您应该重命名该属性viewControllers
,然后在viewDidLoad
循环的末尾,应该将tasks
对象添加到viewControllers
可变数组中,而不是将tasks
设置为nil。 I think that might prevent the crash. 我认为这可以防止崩溃。
for(id name in categories) {
TasksPageViewController *tasks = [self.storyboard instantiateViewControllerWithIdentifier:@"TasksPageViewController"];
...
[scrollView addSubview:tasks.view];
[self.viewControllers addObject:tasks];
i++;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.