简体   繁体   English

表格视图中的“ EXEC_BAD_ACCESS”,“ [[TasksPageViewController tableView:numberOfRowsInSection:]”

[英]'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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM