2016-06-20 4 views
0

Kürzlich wurde meine App dahingehend geändert, dass sie einen Registerkarten-Controller enthält. Ich kann jetzt nicht alle Kategorien laden, die sich in meiner SQLite-Datenbank befinden, wenn die App gestartet wird, und beim Laden der App (CategoriesViewController) zum Navi-Controller der Kategorien-Tabellenansicht wechseln. Es gibt 6 Kategorienamen, die angezeigt werden sollten. manchmal zeigt die App 0 Zeilen an, manchmal zeigt sie 4 an. Wenn ich die XML-Datei ändere, von der die Daten stammen, habe ich 6 Kategorien bekommen (nach ein paar Malen von 0 und schneller Ausführungsgeschwindigkeit). Führt mich dazu zu denken, dass dies mit dem Timing der Ausführung im Vergleich zur Zeit zu tun hat, bis die Tabellenansicht mit Daten geladen ist. Irgendwelche Ideen, was ich ändern muss, damit CategoriesViewController die Tabelle erst anzeigt, nachdem alle Daten gelesen wurden? Hier ist der Code; Bitte lassen Sie mich wissen, ob Sie noch etwas sehen müssen. Vielen Dank!TableView ruft keine Datensätze aus der SQLite-Datenbank ab und zeigt sie nicht an

CategoriesViewController.h

#import <UIKit/UIKit.h> 

@interface CategoriesViewController : UITableViewController 

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; 

- (void)fetch; // Fetches categories from data store 

@end 

CategoriesViewController.m

#import "CategoriesViewController.h" 
#import "ProductsViewController.h" 
#import "Category.h" 
#import "AppDelegate.h" 

@interface CategoriesViewController() // Categories View Controller interface 

@property (nonatomic, strong) ProductsViewController *productController; 
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; 
@property (weak, nonatomic) IBOutlet UIImageView *logoImageView; 

@end 

#pragma mark - 

@implementation CategoriesViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    _logoImageView.image = [UIImage imageNamed:@"company.jpg"]; 

    [self fetch]; // Fetch categories from our data store 
} 

- (void)fetch { 
    NSError *error = nil; 
    BOOL success = [self.fetchedResultsController performFetch:&error]; // Fetch results; if error, assign error code, output message 
    NSAssert2(success, @"Unhandled error performing fetch at CategoriessViewController.m, line %d: %@", __LINE__, [error localizedDescription]); 
} 

- (NSFetchedResultsController *)fetchedResultsController { 
    if (_fetchedResultsController == nil) { 
     NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
     AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
     [fetchRequest setEntity:[NSEntityDescription entityForName:@"Category" inManagedObjectContext:app.managedObjectContext]]; // Fetch categories 
     NSArray *sortDescriptors = nil; 
     NSString *sectionNameKeyPath = nil; 
     sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"order" ascending:YES]]; 
     [fetchRequest setSortDescriptors:sortDescriptors]; 

     _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                     managedObjectContext:app.managedObjectContext 
                      sectionNameKeyPath:sectionNameKeyPath 
                        cacheName:nil]; 
      } 
    return _fetchedResultsController; 
} 

#pragma mark - UITableViewDataSource 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)table { 
    return [[self.fetchedResultsController sections] count]; 
} 

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section { 
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; 
    return [sectionInfo numberOfObjects]; 
} 

- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *kCellIdentifier = @"CategoryCell"; 

    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCellIdentifier forIndexPath:indexPath]; 
    Category *category = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(@"%@", @"%@"), category.name]; 
    return cell; 
} 

// Pass managed object to ProductsViewController 
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    if ([[segue identifier] isEqualToString:@"showProducts"]) { 
     ProductsViewController *detailsController = (ProductsViewController *)[segue destinationViewController]; 
     NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow]; 

     detailsController.category = [self.fetchedResultsController objectAtIndexPath:selectedIndexPath]; 

     AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
     [[segue destinationViewController] setManagedObjectContext:app.managedObjectContext]; 
    } 
} 

@end 

AppDelegate.h

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

@interface AppDelegate : NSObject <UIApplicationDelegate, companyXMLImporterDelegate> 

@property (nonatomic, strong) UIWindow *window; 
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext; 
@property (nonatomic, retain) NSPersistentStoreCoordinator *persistentStoreCoordinator; 

- (NSDate *)lasModificationDateOfFileAtURL:(NSURL *)url; 

@end 

AppDelegate.m

#import "AppDelegate.h" 
#import "ProductsViewController.h" 
#import "CategoriesViewController.h" 

@interface AppDelegate() 

@property (nonatomic, strong) ProductsViewController *productsViewController; 
@property (nonatomic, strong) CategoriesViewController *categoriesViewController; 

// Properties for the importer and its background processing 
@property (nonatomic, strong) companyXMLImporter *importer; 
@property (nonatomic, strong) NSOperationQueue *operationQueue; 

@property (nonatomic, strong) NSString *persistentStorePath; 

@end 

@implementation AppDelegate 

static NSString * const kLastStoreUpdateKey = @"LastStoreUpdate"; // Identifies update object in user defaults storage 

static NSTimeInterval const kRefreshTimeInterval = 3600; 

- (void)applicationDidFinishLaunching:(UIApplication *)application { 
    NSDate *lastUpdate = [[NSUserDefaults standardUserDefaults] objectForKey:kLastStoreUpdateKey]; 
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:NSLocalizedString(@"Products XML", @"Products XML")]]; 
    NSDate *lastModifiedDate = [self lasModificationDateOfFileAtURL:url]; 
    if (lastUpdate == nil || lastModifiedDate >= lastUpdate || -[lastUpdate timeIntervalSinceNow] > kRefreshTimeInterval) { 
     if ([[NSFileManager defaultManager] fileExistsAtPath:self.persistentStorePath]) { 
      NSError *error = nil; 
      BOOL oldStoreRemovalSuccess = [[NSFileManager defaultManager] removeItemAtPath:self.persistentStorePath error:&error]; 
      NSAssert3(oldStoreRemovalSuccess, @"Unhandled error adding persistent store in %s at line %d: %@", __FUNCTION__, __LINE__, [error localizedDescription]); 
     } 

     // Object to retrieve, parse, and import into CoreData store 
     self.importer = [[companyXMLImporter alloc] init]; 
     self.importer.delegate = self; 

     // pass coordinator so importer can create its own managed object context 
     self.importer.persistentStoreCoordinator = self.persistentStoreCoordinator; 

     // URL for products XML file 
     self.importer.companyURL = [NSURL URLWithString:[NSString stringWithFormat:NSLocalizedString(@"Products XML", @"Products XML")]]; 
     [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

     [self.operationQueue addOperation:self.importer]; 
    } 
} 

- (NSOperationQueue *)operationQueue { 
    if (_operationQueue == nil) { 
     _operationQueue = [[NSOperationQueue alloc] init]; 
    } 
    return _operationQueue; 
} 

- (NSDate *)lasModificationDateOfFileAtURL:(NSURL *)url { 
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 

    // Get only header 
    request.HTTPMethod = @"HEAD"; 
    NSHTTPURLResponse *response = nil; 
    NSError *error = nil; 
    [NSURLConnection sendSynchronousRequest:request 
          returningResponse:&response 
             error:&error]; 

    if (error) { 
     NSLog(@"Error: %@", error.localizedDescription); 
     return nil; 
    } else if([response respondsToSelector:@selector(allHeaderFields)]) { 
     NSDictionary *headerFields = [response allHeaderFields]; 
     NSString *lastModification = [headerFields objectForKey:@"Last-Modified"]; 

     NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
     [formatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss zzz"]; 
     return [formatter dateFromString:lastModification]; 
    } 
    return nil; 
} 

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
    if (_persistentStoreCoordinator == nil) { 
     NSURL *storeUrl = [NSURL fileURLWithPath:self.persistentStorePath]; 
     _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]]; 
     NSError *error = nil; 
     NSPersistentStore *persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]; 
     NSAssert3(persistentStore != nil, @"Unhandled error adding persistent store in %s at line %d: %@", __FUNCTION__, __LINE__, [error localizedDescription]); 
    } 
    return _persistentStoreCoordinator; 
} 

- (NSManagedObjectContext *)managedObjectContext { 
    if (_managedObjectContext == nil) { 
     _managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [self.managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 
    } 
    return _managedObjectContext; 
} 

- (NSString *)persistentStorePath { 
    if (_persistentStorePath == nil) { 
     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     NSString *documentsDirectory = [paths lastObject]; 
     _persistentStorePath = [documentsDirectory stringByAppendingPathComponent:@"Company.sqlite"]; 
    } 
    return _persistentStorePath; 
} 

- (void)importerDidSave:(NSNotification *)saveNotification { 
    if ([NSThread isMainThread]) { 
     [self.managedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification]; 
//  [self.categoriesViewController fetch]; 
     [self.productsViewController fetch]; 
    } else { 
     [self performSelectorOnMainThread:@selector(importerDidSave:) withObject:saveNotification waitUntilDone:NO]; 
    } 
} 

// Main-thread import completion processing 
- (void)handleImportCompletion { 
    [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:kLastStoreUpdateKey]; 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
    self.importer = nil; 
} 

- (void)importerDidFinishParsingData:(companyXMLImporter *)importer { 
    [self performSelectorOnMainThread:@selector(handleImportCompletion) withObject:nil waitUntilDone:NO]; 
} 

// Process errors received in delegate callback 
- (void)handleImportError:(NSError *)error { 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
    self.importer = nil; 

    NSString *errorMessage = [error localizedDescription]; 
    NSString *alertTitle = NSLocalizedString(@"Error", @"Title for alert displayed when download or parse error occurs."); 
    NSString *okTitle = NSLocalizedString(@"OK ", @"OK Title for alert displayed when download or parse error occurs."); 

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:alertTitle 
                 message:errorMessage 
                 delegate:nil 
               cancelButtonTitle:okTitle 
               otherButtonTitles:nil]; 
    [alertView show]; 
} 

- (void)importer:(companyXMLImporter *)importer didFailWithError:(NSError *)error { 
    [self performSelectorOnMainThread:@selector(handleImportError:) withObject:error waitUntilDone:NO]; 
} 

@end 

companyXMLImporter.h

#import <UIKit/UIKit.h> 
#import <libxml/tree.h> 

@class companyXMLImporter, Product, Category, CategoryCache; 

@protocol companyXMLImporterDelegate <NSObject> 

@optional 

- (void)importerDidSave:(NSNotification *)saveNotification; // Posted when saved 
- (void)importerDidFinishParsingData:(companyXMLImporter *)importer; // Called when parsing is finished 
- (void)importer:(companyXMLImporter *)importer didFailWithError:(NSError *)error; // Called if error 

@end 

@interface companyXMLImporter : NSOperation { 
@private 
    id <companyXMLImporterDelegate> __unsafe_unretained delegate; 

    // Reference to the libxml parser context 
    xmlParserCtxtPtr context; 
    NSURLConnection *xmlConnection; 

    BOOL done; 

    BOOL parsingAProduct; 

    // Used for getting character data from XML elements 
    BOOL storingCharacters; 
    NSMutableData *characterBuffer; 

    Product *currentProduct; 

    NSUInteger countForCurrentBatch; 
    NSManagedObjectContext *insertionContext; 
    NSPersistentStoreCoordinator *persistentStoreCoordinator; 
    NSEntityDescription *productEntityDescription; 
    CategoryCache *theCache; 
    NSURL *companyURL; 
} 

@property (nonatomic, retain) NSURL *companyURL; 
@property (nonatomic, assign) id <companyXMLImporterDelegate> delegate; 
@property (nonatomic, retain) NSPersistentStoreCoordinator *persistentStoreCoordinator; 
@property (nonatomic, retain, readonly) NSManagedObjectContext *insertionContext; 
@property (nonatomic, retain, readonly) NSEntityDescription *productEntityDescription; 
@property (nonatomic, retain, readonly) CategoryCache *theCache; 

- (void)main; 

@end 

companyXMLImporter.m

#import "companyXMLImporter.h" 
#import "Product.h" 
#import "Category.h" 
#import "CategoryCache.h" 
#import <libxml/tree.h> 

// Function prototypes for SAX callbacks 
static void startElementSAX(void *context, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes); 
static void endElementSAX(void *context, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI); 
static void charactersFoundSAX(void *context, const xmlChar *characters, int length); 
static void errorEncounteredSAX(void *context, const char *errorMessage, ...); 

static xmlSAXHandler simpleSAXHandlerStruct; // Forward reference. Structure defined in full at end of file 

@interface companyXMLImporter() 

@property BOOL storingCharacters; 
@property (nonatomic, retain) NSMutableData *characterBuffer; 
@property BOOL done; 
@property BOOL parsingAProduct; 
@property NSUInteger countForCurrentBatch; 
@property (nonatomic, retain) Product *currentProduct; 
@property (nonatomic, retain) NSURLConnection *xmlConnection; 
@property (nonatomic, retain) NSDateFormatter *dateFormatter; 

@end 

static double lookuptime = 0; 

@implementation companyXMLImporter 

@synthesize companyURL, delegate, persistentStoreCoordinator; 
@synthesize xmlConnection, done, parsingAProduct, storingCharacters, currentProduct, countForCurrentBatch, characterBuffer; 

- (void)main { 
    if (delegate && [delegate respondsToSelector:@selector(importerDidSave:)]) { 
     [[NSNotificationCenter defaultCenter] addObserver:delegate selector:@selector(importerDidSave:) name:NSManagedObjectContextDidSaveNotification object:self.insertionContext]; 
    } 
    done = NO; 
    self.characterBuffer = [NSMutableData data]; 
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:companyURL]; 

    xmlConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; // create connection with request and start loading data 

    context = xmlCreatePushParserCtxt(&simpleSAXHandlerStruct, (__bridge void *)(self), NULL, 0, NULL); 
    if (xmlConnection != nil) { 
     do { 
      [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
     } while (!done); 
    } 

    // Release thread resources 
    xmlFreeParserCtxt(context); 
    self.characterBuffer = nil; 
    self.dateFormatter = nil; 
    self.xmlConnection = nil; 
    self.currentProduct = nil; 
    theCache = nil; 

    NSError *saveError = nil; 
    NSAssert1([insertionContext save:&saveError], @"Unhandled error saving managed object context in import thread: %@", [saveError localizedDescription]); 
    if (delegate && [delegate respondsToSelector:@selector(importerDidSave:)]) { 
     [[NSNotificationCenter defaultCenter] removeObserver:delegate name:NSManagedObjectContextDidSaveNotification object:self.insertionContext]; 
    } 
    if (self.delegate != nil && [self.delegate respondsToSelector:@selector(importerDidFinishParsingData:)]) { 
     [self.delegate importerDidFinishParsingData:self]; 
    } 
} 

- (NSManagedObjectContext *)insertionContext { 
    if (insertionContext == nil) { 
     insertionContext = [[NSManagedObjectContext alloc] init]; 
     [insertionContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 
    } 
    return insertionContext; 
} 

- (void)forwardError:(NSError *)error { 
    if (self.delegate != nil && [self.delegate respondsToSelector:@selector(importer:didFailWithError:)]) { 
     [self.delegate importer:self didFailWithError:error]; 
    } 
} 

- (NSEntityDescription *)productEntityDescription { 
    if (productEntityDescription == nil) { 
     productEntityDescription = [NSEntityDescription entityForName:@"Product" inManagedObjectContext:self.insertionContext]; 
    } 
    return productEntityDescription; 
} 

- (CategoryCache *)theCache { 
    if (theCache == nil) { 
     theCache = [[CategoryCache alloc] init]; 
     theCache.managedObjectContext = self.insertionContext; 
    } 
    return theCache; 
} 

- (Product *)currentProduct { 
    if (currentProduct == nil) { 
     currentProduct = [[Product alloc] initWithEntity:self.productEntityDescription insertIntoManagedObjectContext:self.insertionContext]; 
    } 
    return currentProduct; 
} 

// Forward errors to delegate 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    [self performSelectorOnMainThread:@selector(forwardError:) withObject:error waitUntilDone:NO]; 
    done = YES; // End run loop 
} 

// Called when a chunk of data has been downloaded 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    // Process downloaded chunk of data 
    xmlParseChunk(context, (const char *)[data bytes], [data length], 0); 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    // Signal the context that parsing is complete by passing "1" as last parameter 
    xmlParseChunk(context, NULL, 0, 1); 
    context = NULL; 
    done = YES; // End the loop 
} 

static const NSUInteger kImportBatchSize = 20; 

- (void)finishedCurrentProduct { 
    parsingAProduct = NO; 
    self.currentProduct = nil; 
    countForCurrentBatch++; 

    if (countForCurrentBatch == kImportBatchSize) { 
     NSError *saveError = nil; 
     NSAssert1([insertionContext save:&saveError], @"Unhandled error saving managed object context in import thread: %@", [saveError localizedDescription]); 
     countForCurrentBatch = 0; 
    } 
} 

// Character data appended to a buffer until current element ends. 
- (void)appendCharacters:(const char *)charactersFound length:(NSInteger)length { 
    [characterBuffer appendBytes:charactersFound length:length]; 
} 

- (NSString *)currentString { 
    // Create a string with character data using UTF-8 encoding 
    NSString *currentString = [[NSString alloc] initWithData:characterBuffer encoding:NSUTF8StringEncoding]; 
    [characterBuffer setLength:0]; 
    return currentString; 
} 

@end 

// XML element names, string lengths for parsing 
static const char *kName_App = "App"; // Product container tag 
static const NSUInteger kLength_App = 4; 
static const char *kName_Sku = "prod_sku"; 
static const NSUInteger kLength_Sku = 9; 
static const char *kName_Name = "prod_name"; 
static const NSUInteger kLength_Name = 10; 
static const char *kName_Description = "prod_description"; 
static const NSUInteger kLength_Description = 17; 
static const char *kName_Category = "prod_category"; 
static const NSUInteger kLength_Category = 14; 
static const char *kName_Upc = "prod_upc"; 
static const NSUInteger kLength_Upc = 9; 
static const char *kName_CountryCode = "prod_code_destination"; 
static const NSUInteger kLength_CountryCode = 22; 
static const char *kName_Webpage = "prod_html_link"; 
static const NSUInteger kLength_Webpage = 15; 
static const char *kName_Manual = "prod_manual"; 
static const NSUInteger kLength_Manual = 12; 
static const char *kName_QuickStart = "prod_quick_start"; 
static const NSUInteger kLength_QuickStart = 17; 
static const char *kName_Thumbnail = "prod_thumbnail"; 
static const NSUInteger kLength_Thumbnail = 15; 
static const char *kName_MainImage = "prod_image_main"; 
static const NSUInteger kLength_MainImage = 16; 
static const char *kName_SecondaryImage = "prod_image_secondary"; 
static const NSUInteger kLength_SecondaryImage = 21; 

// Invoked when importer finds beginning of a node 
static void startElementSAX(void *parsingContext, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, 
          int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes) { 

    companyXMLImporter *importer = (__bridge companyXMLImporter *)parsingContext; 

    if (!strncmp((const char *)localname, kName_App, kLength_App)) { 
     importer.parsingAProduct = YES; 
     } else if (importer.parsingAProduct && ((!strncmp((const char *)localname, kName_Sku, kLength_Sku) || !strncmp((const char *)localname, kName_Name, kLength_Name) || !strncmp((const char *)localname, kName_Description, kLength_Description) || !strncmp((const char *)localname, kName_Category, kLength_Category) || !strncmp((const char *)localname, kName_Upc, kLength_Upc) || !strncmp((const char *)localname, kName_CountryCode, kLength_CountryCode) || !strncmp((const char *)localname, kName_Webpage, kLength_Webpage) || !strncmp((const char *)localname, kName_Manual, kLength_Manual) || !strncmp((const char *)localname, kName_QuickStart, kLength_QuickStart) || !strncmp((const char *)localname, kName_Thumbnail, kLength_Thumbnail) || !strncmp((const char *)localname, kName_MainImage, kLength_MainImage) || !strncmp((const char *)localname, kName_SecondaryImage, kLength_SecondaryImage))) 
        ) { 
     importer.storingCharacters = YES; 
    } 
} 

// Invoked when parse reaches end of a node 
static void endElementSAX(void *parsingContext, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI) { 
    companyXMLImporter *importer = (__bridge companyXMLImporter *)parsingContext; 

    if (importer.parsingAProduct == NO) return; 
    if (!strncmp((const char *)localname, kName_App, kLength_App)) { 
     [importer finishedCurrentProduct]; 
    } else if (!strncmp((const char *)localname, kName_Name, kLength_Name)) { 
     importer.currentProduct.name = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_Category, kLength_Category)) { 
     double before = [NSDate timeIntervalSinceReferenceDate]; 
     Category *category = [importer.theCache categoryWithName:importer.currentString]; 
     double delta = [NSDate timeIntervalSinceReferenceDate] - before; 
     lookuptime += delta; 
     importer.currentProduct.category = category; 
    } else if (!strncmp((const char *)localname, kName_Sku, kLength_Sku)) { 
     importer.currentProduct.sku = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_Description, kLength_Description)) { 
     importer.currentProduct.prodDescription = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_Upc, kLength_Upc)) { 
     importer.currentProduct.upc = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_CountryCode, kLength_CountryCode)) { 
     importer.currentProduct.countryCode = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_Webpage, kLength_Webpage)) { 
     importer.currentProduct.webpage = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_Manual, kLength_Manual)) { 
     importer.currentProduct.manual = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_QuickStart, kLength_QuickStart)) { 
     importer.currentProduct.quickStart = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_Thumbnail, kLength_Thumbnail)) { 
     importer.currentProduct.thumbURLString = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_MainImage, kLength_MainImage)) { 
     importer.currentProduct.mainImgURLString = importer.currentString; 
    } else if (!strncmp((const char *)localname, kName_SecondaryImage, kLength_SecondaryImage)) { 
     importer.currentProduct.secondaryImgURLString = importer.currentString; 
    } 
    importer.storingCharacters = NO; 
} 

// Invoked when parser encounters character data inside a node 
static void charactersFoundSAX(void *parsingContext, const xmlChar *characterArray, int numberOfCharacters) { 
    companyXMLImporter *importer = (__bridge companyXMLImporter *)parsingContext; 

    // storingCharacters set when nodes of interest begin/end – determines whether character data handled/ignored 
    if (importer.storingCharacters == NO) return; 
    [importer appendCharacters:(const char *)characterArray length:numberOfCharacters]; 
} 

// Error handling 
static void errorEncounteredSAX(void *parsingContext, const char *errorMessage, ...) { 
    // Handle errors as appropriate 
    NSCAssert(NO, @"Unhandled error encountered during SAX parse."); 
} 

static xmlSAXHandler simpleSAXHandlerStruct = { 
    NULL, /* internalSubset */ 
    NULL, /* isStandalone */ 
    NULL, /* hasInternalSubset */ 
    NULL, /* hasExternalSubset */ 
    NULL, /* resolveEntity */ 
    NULL, /* getEntity */ 
    NULL, /* entityDecl */ 
    NULL, /* notationDecl */ 
    NULL, /* attributeDecl */ 
    NULL, /* elementDecl */ 
    NULL, /* unparsedEntityDecl */ 
    NULL, /* setDocumentLocator */ 
    NULL, /* startDocument */ 
    NULL, /* endDocument */ 
    NULL, /* startElement*/ 
    NULL, /* endElement */ 
    NULL, /* reference */ 
    charactersFoundSAX, /* characters */ 
    NULL, /* ignorableWhitespace */ 
    NULL, /* processingInstruction */ 
    NULL, /* comment */ 
    NULL, /* warning */ 
    errorEncounteredSAX, /* error */ 
    NULL,/* fatalError //: unused error() get all the errors */ 
    NULL, /* getParameterEntity */ 
    NULL, /* cdataBlock */ 
    NULL, /* externalSubset */ 
    XML_SAX2_MAGIC, // 
    NULL, 
    startElementSAX, /* startElementNs */ 
    endElementSAX, /* endElementNs */ 
    NULL, /* serror */ 
}; 
+0

Laden Sie Ihre Tabellenansicht in 'fetchedResultsController' Methode nach dem' _fetchedResultsController' initialisieren Linie –

+0

Sie sagen, dass Sie in SQL-db geändert, aber der Code ist für Core-Daten. Bitte aktualisieren Sie den Code. –

Antwort

0

Sie sollten nicht reload anrufen müssen auf alle Daten zu erhalten, die in der Tabelle angezeigt werden ... und du bist es ruft zweimal, in viewDidLoad und in holen. Ich würde diese loswerden.

Es klingt wie Sie haben ein Timing-Problem. Können Sie mehr darüber erklären, wie die Daten in die Datenbank gelangen? Wenn Sie sagen,

die XML-Datei In geändert wird, wie diese Daten in der Datenbank zieht aus ...

Ich nehme an, Sie meinen, dass, wenn die App gestartet wird, ist es aus einer XML-Datei liest die ist mit Ihrer App gepackt und schreibt diese Informationen in Core Data/SQLite. Wenn dies tatsächlich der Fall ist, besteht das Problem möglicherweise darin, dass dieser Prozess gleichzeitig mit dem Laden des CategoriesViewController ausgeführt wird. Wo ist der Code, der die XML in Core Data/SQLite liest? Woher nennst du es? Ist es ein synchroner oder ein asynchroner Aufruf?

+0

Danke, Brett! Ich habe verwandte Dateien hinzugefügt und die reloadDatas entfernt. Ja, du hast es besser formuliert als ich! Es gibt ein XML-Importer, der die Daten aus der XML-Datei (unter einer URL) in die Datenbank zieht (siehe oben). Dies wird im App-Delegaten aufgerufen, und ich glaube, dass es synchron ist. – techsomniac

+0

Ich denke, ich habe es herausgefunden. Ich entfernte die Zeile "[self.operationQueue addOperation: self.importer]" in AppDelegate.m und ersetzte diese Zeile durch [self.importer main], und dies schien das Problem zu beheben. Sie liefen wahrscheinlich gleichzeitig. Danke für die Hilfe! – techsomniac

+0

Eine Operationswarteschlange ist asynchron, also hat ja das Wechseln zu einem synchronen Aufruf geholfen. Aber ich kann mir eine potenziell bessere Lösung vorstellen.Sie verwenden einen NSFetchedResultsController, eine sehr nützliche Klasse, die die Datenbank auf Änderungen überwacht und ihren Delegaten benachrichtigt, wenn Änderungen festgestellt werden. Sie sollten über CategoriesViewController das NSFetchedResultsControllerDelegate-Protokoll implementieren und den Delegaten des abgerufenen Ergebnis-Controllers auf Ihren Kategorien-View-Controller (self) festlegen. Auf diese Weise können Sie Ihr XML asynchron abrufen und Ihre App wird sich schneller anfühlen. –

Verwandte Themen