2013-07-30 22 views
6

Sto utilizzando un modello Core Data e una vista tabella UITableViewController. La mia modella sembra funzionare abbastanza bene, tuttavia la mia vista tabella non viene aggiornata quando aggiungo un'entità al mio modello. La ragione per cui ritengo che il mio modello funzioni è che quando aggiungo un'entità non compare nulla nella vista durante il runtime, tuttavia se taglio l'attività, la avvio in modo nuovo, all'improvviso l'entità precedentemente creata appare nella vista tabella.UITableView non si aggiorna

Ecco il mio controller della vista tabella - AudioTableViewController.h

#import <UIKit/UIKit.h> 
#import "Bank.h" 
#import "Player.h" 

@class Player; 
@interface AudioTableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> { 
    Player *myMainMan; 
} 

-(void)addAudioEntityToArray:(AudioFile *)event; 
-(NSMutableArray *)recordingsArray; 

@end 

AudioTableViewController.m (file di implementazione)

#import "AudioTableViewController.h" 

@implementation AudioTableViewController 

-(void)addAudioEntityToArray:(AudioFile *)event { 
    NSIndexPath *indexPath; 

    if(event.type) { 
     [[MusikerViewController recordingsArray] addObject:event];//self? 
     indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 
    }else { 
     [[MusikerViewController downloadsArray] addObject:event]; 
     indexPath = [NSIndexPath indexPathForRow:0 inSection:1]; 
    } 

    [[self tableView] setEditing:YES animated:NO]; 
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
         withRowAnimation:UITableViewRowAnimationNone]; 
} 


- (void)viewDidLoad { 
     [[self tableView] reloadData]; 
     [super viewDidLoad]; 

     self.title = @"Audio Files";//put this in application delegate 

     self.navigationItem.leftBarButtonItem = self.editButtonItem; 
} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    // Return the number of sections. 
    return 2; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    // Return the number of rows in the section.  

    NSLog(@"Place I"); 

    if(section == 0) { 
     return [[MusikerViewController recordingsArray] count]; 
    } else if (section == 1) { 
     return [[MusikerViewController downloadsArray] count]; 
    } 
} 

... più metodi

Ecco parte della mia banca classe che potrebbe essere rilevante Bank.h

#import <Foundation/Foundation.h> 
#import <AudioToolbox/AudioToolbox.h> 
#import "AudioFile.h" 
#import "AudioTableViewController.h" 
#import "MusikerAppDelegate.h" 

@interface Bank : NSObject <UIAlertViewDelegate> { 
    NSManagedObjectContext *managedObjectContext; 
    AudioFile *sound; 
} 

@property (retain, nonatomic) NSManagedObjectContext *managedObjectContext; 

+(NSString *)getDataPath:(NSString *)fileExtDate; 

-(AudioFile *)addAudioFileEntityToModelWithDate:(NSDate *)theD andURLString:(NSString *)str; 
-(BOOL)removeAudioFromModel:(id)audio; 
-(NSMutableArray *)getFetchArray; 

@end 

Bank.m

#import "Bank.h" 

@implementation Bank 
@synthesize managedObjectContext; 

- (AudioFile *)addAudioFileEntityToModelWithDate:(NSDate *)theD andURLString:(NSString *)str { 
    sound = (AudioFile *)[NSEntityDescription insertNewObjectForEntityForName:@"AudioFile" inManagedObjectContext:managedObjectContext]; 

    sound.creationDate = theD; 
    sound.soundPath = str; //set the sound path to the sound file's url 
    [self alertForTitle]; 

    return sound; 
} 

- (BOOL)saveContext { 
    NSError *error = nil; 
    if(!managedObjectContext) { 
     NSLog(@"managedObejctContext problem at saveContext Bank"); 
    } 

    if (![managedObjectContext save:&error]) { 
     return NO; 
    } else { 
     return YES; 
    } 
} 

- (NSMutableArray *)getFetchArray { 

    NSLog(@"ManagedObjectContext at getFetchArray"); 
    NSLog(@"Context: %@",managedObjectContext); 

    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    if(!managedObjectContext) { 
     NSLog(@"There is no managedObjectContext in getFetchArray Bank"); 
    } 
     NSEntityDescription *entity = [NSEntityDescription entityForName:@"AudioFile" inManagedObjectContext:managedObjectContext]; 
    [request setEntity:entity]; 

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
    [request setSortDescriptors:sortDescriptors]; 
    [sortDescriptors release]; 
    [sortDescriptor release]; 

    NSError *error = nil; 
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; 
    if (mutableFetchResults == nil) { 
     NSLog(@"mutableFetchResults array is nil"); 
    } 
    [request release]; 
    return mutableFetchResults; 
} 

+ (NSString *)getDataPath:(NSString *)fileExtDate { 

    NSLog(@"getDataPath called"); 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    documentsDirectory = [documentsDirectory stringByAppendingPathComponent:@"Musik Directory"];   //changing the recording directory to Musik Directory 

    NSError *error; 
    if (![[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory]) { 
    [[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectory withIntermediateDirectories:YES attributes:nil error:&error]; 
     NSLog(@"In the if statement"); 
    } 

    NSString *docPath = [documentsDirectory stringByAppendingPathComponent:fileExtDate]; 

    return docPath; 

} 

Player.h

#import <Foundation/Foundation.h> 
#import <AVFoundation/AVFoundation.h> 
#import "Bank.h" 

@class Bank; 
@interface Player : NSObject <AVAudioPlayerDelegate, AVAudioRecorderDelegate> { 

Bank *daBank; 

AVAudioPlayer *musicPlayer; 
AVAudioRecorder *musicRecorder; 

NSDate *myDate; 
NSString *strPath; 

NSString *documentPath_; 
NSMutableArray *arrayListOfRecordSound; 
} 

-(void)playSoundFile:(NSString *)soundFilePath; 
-(BOOL)saveRecordingWithDate:(NSDate *)theD andURLString:(NSString *)str; 
-(void)recordSomething; 
-(void)playRecording; 
-(void)play; 

+ (NSString *)dateString:(NSDate *)date; 
+ (NSString *)dateString; 

@end 

Player.m

- (Bank *)daBank 
{  
    if(!daBank) { 
     daBank = [[Bank alloc] init]; 
    } 

    return daBank; 
} 

-(BOOL)saveRecording { //this is the method that adds the new object to both the //model and view, the method that calls this method is not shown 
    Bank *B = [MusikerViewController daBank]; 
    AudioTableViewController *ATVC2 = [MusikerViewController ATVControl]; 
    AudioFile *myAudioFileMusicX314 = [[B addAudioFileEntityToModelWithDate:myDate andURLString:strPath] retain]; 

    myAudioFileMusicX314.type = true; 

    [ATVC2 addAudioEntityToArray:myAudioFileMusicX314]; 

    if(![B saveContext]) { 
     NSLog(@"addAudioFileEntityToModel is returning a nil managedObjectContext"); 
     return NO; 
    } 

    [myDate release]; 
    [strPath release]; 
    [myAudioFileMusicX314 release]; 
[ATVC2 release]; 

    return YES;    
} 

Ultimo ma non meno importante, MusikViewController.h

#import <UIKit/UIKit.h> 
#import "Player.h" 
#import "Bank.h" 
#import <QuartzCore/QuartzCore.h> 
#import "MyButtonView.h" 
#import "AudioTableViewController.h" 

@class AudioTableViewController; 
@class Bank; 
@class Player; 
@interface MusikerViewController : UIViewController { 
] BOOL *pressed; 
} 

Player *myMainMan; 
Bank *daBank; 
AudioTableViewController *ATVControl; 
NSMutableArray *recordingsArray; 
NSMutableArray *downloadsArray; 

+ (Bank *)daBank; 
+ (Player *)myMainMan; 
+ (AudioTableViewController *)ATVControl; 
+ (NSMutableArray *)recordingsArray; 
+ (NSMutableArray *)downloadsArray; 

@end 

MusikViewController.m

+ (NSMutableArray *)recordingsArray { 
    NSLog(@"recordingsArray called"); 

    if(!recordingsArray) { 
     recordingsArray = [[NSMutableArray alloc] init]; 
     NSMutableArray *bigTempArray = [[[[Bank alloc] init] autorelease] getFetchArray]; //change this 
     for(AudioFile *af in bigTempArray) 
      if(af.type) { 
       [recordingsArray addObject:af]; 
      } 
     NSLog(@"recordingsArray exists"); 
    } 
    return recordingsArray; 
} 

+ (NSMutableArray *)downloadsArray { 
    NSLog(@"recordingsArray called"); 

    if(!downloadsArray) { 
     downloadsArray = [[NSMutableArray alloc] init]; 
     // if(!bigTempArray) 
     NSMutableArray *bigTempArray = [[[[Bank alloc] init] autorelease] getFetchArray]; 
     for(AudioFile *af in bigTempArray) 
      if(!af.type) { 
       [downloadsArray addObject:af]; 
      } 
    } 
    return downloadsArray; 
} 

Se ci sono altri metodi che potrebbero essere rilevanti, me lo faccia sapere e sarò felice di pubblicarle.

Vorrei anche menzionare che, dopo aver lanciato l'app, posso aggiungere una singola entità all'array, ma dopo lo stesso problema.

+0

inviare un vostro 'metodo numberOfRows' – user2545330

+0

Is addAudioEntityToArray eseguita sul thread principale? –

+0

@HermannKlecker sì – luca590

risposta

3

Penso che il tuo problema sia l'architettura dei tuoi controller di visualizzazione.Prova questo:

1) Impostare tutto lo stack di dati di base nel delegato dell'app. Passa il contesto dell'oggetto gestito associato a tutti i tuoi controller di visualizzazione come una proprietà. Questo è lo schema utilizzato da Apple in molti dei suoi esempi di codice di esempio.

2) Per ogni controller di visualizzazione tabella, creare proprioNSFetchedResultsController, normalmente anche come proprietà. Utilizza gli esempi Apple come guida.

3) Mai recuperare dati da un altro controller di visualizzazione, come nel codice. Non è possibile e non è necessario ottenere i dati della tabella per da MusikerViewController.

È possibile e talvolta utile disporre di un oggetto dati centrale che fornisce dati per visualizzare i controller. Non è possibile avere questo oggetto dati come controller di visualizzazione. Questa è una violazione palese (e nel tuo caso fatale) del modello di progettazione MVC. Molto probabilmente il tuo errore deriva da quello (perché lo MusikerViewController non è sullo schermo e potrebbe anche essere deallocato).

4) Assicurarsi che nei metodi datasource si usi solo il controller dei risultati recuperato per popolare le tabelle e recapitare i supporti.

+0

Puoi fornire un codice reale. Voglio essere sicuro di fare esattamente quello che stai suggerendo, quindi so se funziona o meno – luca590

+0

Inizia con un nuovo progetto (dettaglio principale) e controlla "Dati principali". Basta copiare incolla. – Mundi

+0

quale classe dovrebbe mantenere le registrazioniArray e downloadArray e dovrei dichiararle come proprietà? – luca590

0

si sta impostando eventsArray via setter:

[self setEventsArray:[daBank getFetchArray]]; 

Perché non accedervi tramite getter? Si potrebbe utilizzare un altro esempio di matrice

self.eventsArray o [self eventsArray]

+0

che potrebbe rendere il codice un po 'più leggibile ma non ha risolto il problema Grazie comunque al numero – luca590

5

può essere la vostra - (void) addAudioEntityToArray: (AudioFile *) evento {} metodo viene chiamato dal thread secondario (diversi dai filati MainUi) in modo che direttamente la tabella di ricarica non funzionerà.

cercano invece

[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; 

Speranza che aiuta !!

+0

incollalo sopra [self.tableView reloadData]? – luca590

+0

ho provato ad incollare il codice ur su [self.tableView reloadData] ma non ha fatto alcuna differenza. – luca590

+0

try remove NSIndexPath * indexPath = [NSIndexPath indexPathForRow: 0 inSection: 0]; [self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject: indexPath] withRowAnimation: UITableViewRowAnimationFade]; [self.tableView scrollToRowAtIndexPath: [NSIndexPath indexPathForRow: 0 inSection: 0] atScrollPosition: UITableViewScrollPositionTop animato: YES]; e quindi aggiungi il metodo di ricarica. –

0

Suggerisco di utilizzare un controller fetchresults, ho usato array prima, ma molto meglio con FRC.

+0

. Lo provo, ma l'array che sto ricevendo da NSFetchResult è l'array corretto con tutte le informazioni giuste, quindi sarei sorpreso se il il problema era lì, ma non hai mai knoe, malato sicuramente dare un colpo. Grazie! – luca590

+0

Non ho trovato risultati diversi – luca590

1

Aggiungi [self.tableView reloadData] nel metodo addAudioEntityToArray alla fine. Questo costringerà UITableView a ricaricarsi dal modello dopo ogni inserimento.

+0

Ive ha provato quello in circa ogni metodo che potrei pensare di – luca590

0

Nella tua addAudioEntityToArray metodo di chiamata a addObject aggiungerà il nuovo evento al FINE della matrice, non l'inizio.

Perciò l'indexPath che è necessario inviare a insertRowsAtIndexPaths è: come [NSIndexPath indexPathForRow:[MusikerViewController recordingsArray].count-1 inSection:0]

+0

Ho provato anche quello – luca590

Problemi correlati