«EXEC_BAD_ACCESS» в табличном представлении, «[TasksPageViewController tableView: numberOfRowsInSection:]» - PullRequest
1 голос
/ 13 февраля 2012

Я пытался решить эту плохую ссылку уже 2 дня, но не могу найти исправление.

Мое приложение представляет собой базовый список дел с несколькими страницами (UIPageControl) для разных категорий и первой страницей со статистикой о задачах, выполненных пользователем. (если у вас есть 3 категории, вы получите 4 страницы).

Он загружает массив категорий из NSUserDefaults, который может быть изменен модальным представлением, доступным через UIButton точно так же, как (i) в приложении wheather.

Page Control создается классом ViewController (который является основным видом). Для каждого элемента в массиве категорий контроллер представления генерирует новый экземпляр класса TasksPageViewController и создает для него представление раскадровки.

Все работало нормально, пока я не поместил UITableView в представление TasksPageViewController в раскадровке и связал его источник данных с тем же классом.

После реализации необходимых классов для источника данных UITableView в TasksPageViewController он работает нормально, но если я пытаюсь перейти к модальному представлению для изменения категорий, когда я нажимаю DONE (и он должен перезагрузить ViewController и перестроить много страниц для UIPageControll), приложение падает с EXEC_BAD_ACCESS.

Отладка с NSZombiesEnabled, я получил:

2012-02-12 18: 55: 49.460 Понтиньюс [25601: fe03] * - [TasksPageViewController tableView: numberOfRowsInSection:]: сообщение отправлено освобожденному экземпляру 0x68c3040

Но я не знаю, как поступить, я не знаю, какой объект, который был выпущен, я вызываю.

Сценарии следующие:

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

#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

#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

#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;
}

Спасибо.

EDIT: очевидно, ViewController не сохраняет ссылку на TasksPageViewController и UITableView не может найти его источник данных. Я действительно не знаю, как сохранить это с помощью ARC.

1 Ответ

0 голосов
/ 13 февраля 2012

В вашем ViewController viewDidLoad, когда вы просматриваете категории, вы создаете экземпляр TasksPageViewController с именем tasks, но тогда вы нигде не сохраняете ссылку.Поэтому позже TasksPageViewController не может быть найден при отправке сообщения * 1003. *

Я вижу, что в вашем ViewController вы синтезируете свойство с именем views, но тогда вы нигде не используете это свойство.Возможно, вам следует переименовать это свойство viewControllers, а затем в конце цикла в viewDidLoad вы должны добавить свой объект tasks в изменяемый массив viewControllers вместо установки tasks в ноль.Я думаю, что это может предотвратить аварию.

for(id name in categories) {

    TasksPageViewController *tasks = [self.storyboard instantiateViewControllerWithIdentifier:@"TasksPageViewController"];

    ... 

    [scrollView addSubview:tasks.view];
    [self.viewControllers addObject:tasks];
    i++;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...