2

Je construis une application simple avec un onglet de barre personnalisée qui charge le contenu du ViewController à partir d'un UITableView situé dans un autre ViewController. Cependant, chaque fois que j'essaie de faire défiler sur la tableview, j'obtiens une erreur exc_bad_access. J'ai activé NSzombies et garde malloc pour obtenir plus d'informations sur le problème.Erreur EXC_BAD_ACCESS sur un UITableView avec ARC?

Dans la console je reçois:

"message sent to deallocated instance 0x19182f20" 

et après profilage je reçois:

# Address    Category     Event Type RefCt  Timestamp Size Responsible Library Responsible Caller 
56 0x19182f20   FirstTabBarViewController Zombie  -1  00:16.613.309 0 UIKit     -[UIScrollView(UIScrollViewInternal) _scrollViewWillBeginDragging] 

Voici un peu du code de la ViewController où l'erreur se produit: .h :

#import <UIKit/UIKit.h> 
#import "DataController.h" 

@interface FirstTabBarViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> { 
    IBOutlet UITableView* tabBarTable; 
} 

@property (strong, nonatomic) IBOutlet UIView *mainView; 
@property (strong, nonatomic) IBOutlet UITableView *tabBarTable; 
@property (nonatomic, strong) DataController *messageDataController; 

@end 

fichier .m:

#import "FirstTabBarViewController.h" 
#import "DataController.h" 

@interface FirstTabBarViewController() 

@end 

@implementation FirstTabBarViewController 
@synthesize tabBarTable=_tabBarTable; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     // Custom initialization 
    } 
    return self; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

- (void)awakeFromNib 
{ 
    [super awakeFromNib]; 
    self.messageDataController=[[DataController alloc] init]; 
} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 1; 
} 

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 
    return [self.messageDataController countOfList]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *CellIdentifier = @"mainCell"; 
    UITableViewCell *cell = [tableView 
          dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil){ 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
    }; 

    NSString *expenseAtIndex = [self.messageDataController 
            objectInListAtIndex:indexPath.row]; 
    [[cell textLabel] setText:expenseAtIndex]; 
    return cell; 
} 


- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // Return NO if you do not want the specified item to be editable. 
    return NO; 
} 

@end 

Ce FirstTabBarViewController est chargé dans le MainViewController avec le Segue personnalisé suivant:

#import "customTabBarSegue.h" 
#import "MainViewController.h" 

@implementation customTabBarSegue 

-(void) perform { 
    MainViewController *src= (MainViewController *) [self sourceViewController]; 
    UIViewController *dst=(UIViewController *)[self destinationViewController]; 

    for (UIView *view in src.placeholderView.subviews){ 
     [view removeFromSuperview]; 
    } 

    src.currentViewController =dst; 
    [src.placeholderView addSubview:dst.view]; 



} 
@end 

La classe Datacontroller est juste un NSMutableArray simple contenant des chaînes. J'utilise ARC, donc je ne comprends pas d'où vient l'erreur de gestion de la mémoire. Est-ce que quelqu'un a une idée?

Toute aide très appréciée;) Merci !!

+0

« Quelqu'un at-il une idée? » - sans code? No. – Kreiri

+0

S'il vous plaît code postal. –

+0

désolé, je viens d'ajouter du code - merci pour votre aide – Spearfisher

Répondre

0

Ok ... Merci pour l'exemple de code ...

Voir UIStoryboardSegue documentation, lorsque vous implémentez perform dans votre customTabBarSegue, vous êtes responsable de la mise, à la fin, la relation correcte entre votre 2 viewControllers. Vous avez 2 possibilités:

  • cadre dst comme un enfant modal (alors src est presentingViewController dst), en ajoutant ce code à la fin de perform: [src presentViewController:dst animated:NO completion:nil];

  • cadre dst comme un enfant viewController de src - l'ajout de ce code: [src addChildViewController:dst]; à la fin de perform, mais, il faut l'enlever quelque part, ou supprimer d'autres Childs dans la même méthode ....

Voici une implémentation

@implementation customTabBarSegue 

-(void) perform { 
    MainViewController *src= (MainViewController *) [self sourceViewController]; 
    UIViewController *dst=(UIViewController *)[self destinationViewController]; 

    for (UIView *view in src.placeholderView.subviews){ 
     [view removeFromSuperview]; 
    } 

    src.currentViewController =dst; 
    [src.placeholderView addSubview:dst.view]; 

    // this container only show 1 viewController at a time, so we can remove previous ones 
    for (UIViewController *vc in src.childViewControllers) { 
     [vc.view removeFromSuperview]; 
     [vc removeFromParentViewController]; 
    } 
    //then add the new View controller as child 
    [src addChildViewController:dst]; 

} 
@end 

Quoi qu'il en soit, vous devriez regarder définitivement plus dans le confinement UIViewController ...

+0

Je plongerai profondément dans le confinement UIViewController. Merci beaucoup pour cela! – Spearfisher

+0

modifier avec l'enlèvement approprié des enfants avant d'ajouter le nouveau – Vinzzz

Questions connexes