Skip to content

Instantly share code, notes, and snippets.

@omnifroodle
Created February 27, 2010 18:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save omnifroodle/316865 to your computer and use it in GitHub Desktop.
Save omnifroodle/316865 to your computer and use it in GitHub Desktop.
#import <UIKit/UIKit.h>
@interface NewsListViewController : UITableViewController <NSFetchedResultsControllerDelegate>{
NSFetchedResultsController *resultsController;
UIButton *sponsor;
}
@property (nonatomic, retain) NSFetchedResultsController *resultsController;
@end
NSInteger intSort(id num1, id num2, void *context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
- (int) getMaxUpdated: (NSString*)entityName key: (NSString*)keyName {
int result = 0;
[self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// Specify that the request should return dictionaries.
[request setResultType:NSDictionaryResultType];
// Create an expression for the key path.
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:keyName];
// Create an expression to represent the max value at the key path
NSExpression *maxExpression = [NSExpression expressionForFunction:@"max:" arguments:[NSArray arrayWithObject:keyPathExpression]];
// Create an expression description using the minExpression and returning a date.
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
// The name is the key that will be used in the dictionary for the return value.
[expressionDescription setName:[NSString stringWithFormat:@"max%@", keyName]];
[expressionDescription setExpression:maxExpression];
[expressionDescription setExpressionResultType:NSInteger64AttributeType];
// Set the request's properties to fetch just the property represented by the expressions.
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
// Execute the fetch.
NSError *error;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
if (objects == nil) {
// Handle the error.
} else {
if ([objects count] > 0) {
result = [[[objects objectAtIndex:0] valueForKey:[NSString stringWithFormat:@"max%@", keyName]] intValue];
}
}
[expressionDescription release];
[request release];
return result;
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[self createEditableCopyOfDatabaseIfNeeded];
UIView *backgroundView = [[UIView alloc] initWithFrame: window.frame];
backgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background.png"]];
[window addSubview:backgroundView];
[backgroundView release];
[window addSubview:tabcontroller.view];
[window makeKeyAndVisible];
// TODO implement fetching of most recent records
int maxNews = [self getMaxUpdated:@"News" key:@"updated"];
int maxOccasion = [self getMaxUpdated:@"Occasion" key:@"updated"];
NSLog([NSString stringWithFormat:@"max news timestamp %d", maxNews]);
self.lastNews = [NSString stringWithFormat:@"%d", maxNews];
NSLog([NSString stringWithFormat:@"max news timestamp %@", self.lastNews]);
NSLog([NSString stringWithFormat:@"max event timestamp %d", maxOccasion]);
self.lastOccasion = [NSString stringWithFormat:@"%d", maxOccasion];
[NSThread detachNewThreadSelector: @selector(syncNewsFeed:)
toTarget: self withObject: self];
[NSThread detachNewThreadSelector: @selector(syncOccasionFeed:)
toTarget: self withObject: self];
//[self syncOccasionFeed];
}
/**
syncNewsFeed: check for updates to the news feed
*/
- (void)syncNewsFeed:(id)sender {
NSAutoreleasePool *newsPool = [[NSAutoreleasePool alloc] init];
NSLog(@"fetching news");
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@/stories.plist?last=%@", SERVER, self.lastNews]]];
[self performSelectorOnMainThread:@selector(updateNewsData:) withObject:dict waitUntilDone:YES];
[newsPool release];
[NSThread exit];
}
- (void)updateNewsData:(id)dictionary {
if (dictionary == nil) {
return;
}
NSDictionary *dict = dictionary;
NSLog(@"count: %@", [NSString stringWithFormat:@"%d", [dict count]]);
/*for (id key in dict) {
NSLog(@"key: %@, value: %@", key, [dict objectForKey:key]);
}*/
NSArray *storyIDs = [[dict allKeys]
sortedArrayUsingFunction:intSort context:NULL];
// create the fetch request to get all Stories matching the IDs
[self managedObjectContext];
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"News" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity: entity];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat: @"(storyId IN %@)", storyIDs]];
// make sure the results are sorted as well
[fetchRequest setSortDescriptors: [NSArray arrayWithObject:
[[[NSSortDescriptor alloc] initWithKey: @"storyId"
ascending:YES] autorelease]]];
NSError *error;
NSArray *storiessMatchingNames = [managedObjectContext
executeFetchRequest:fetchRequest error:&error];
NSEnumerator *newStoryIterator = [storyIDs objectEnumerator];
NSEnumerator *existingStoryIterator = [storiessMatchingNames objectEnumerator];
// iterate though the sorted arrays updating existing records or adding new ones
News *existingStory;
existingStory = [existingStoryIterator nextObject];
id newStory;
NSManagedObject *newMO;
NSLog(@"existing story count: %@", [NSString stringWithFormat:@"%d", [storyIDs count]]);
while (newStory = [newStoryIterator nextObject]) {
if ((existingStory != nil) & ([newStory intValue] == [existingStory.storyId intValue])) {
NSLog(@"newStory %@ existingStory %@", newStory, [existingStory storyId]);
// update the story with the new version
[existingStory setValuesForKeysWithDictionary:[dict objectForKey:newStory]];
existingStory = [existingStoryIterator nextObject];
} else {
NSLog(@"newStory %@", newStory);
newMO = [[NSManagedObject alloc] initWithEntity:entity
insertIntoManagedObjectContext:managedObjectContext];
[newMO setValuesForKeysWithDictionary:[dict objectForKey:newStory]];
[newMO release];
}
}
}
- (void) createEditableCopyOfDatabaseIfNeeded {
// first, test for existence - we don't want to wipe out a user's DB
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsDirectory = [self applicationDocumentsDirectory];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"USITT_2010.sqlite"];
BOOL dbexists = [fileManager fileExistsAtPath:writableDBPath];
if (!dbexists) {
// The writable database does not exist, so copy the default to the appropriate location
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"USITT_2010.sqlite"];
NSError *error;
BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0 , @"Failed to create writable database with message '%@'.", [error localizedDescription]);
}
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.resultsController != nil) {
return;
}
MyAppDelegate *appDelegate = (MyAppDelegate*)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"News" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
//NSPredicate *predicate = [NSPredicate predicateWithFormat:@"captured == YES"];
//[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"captured_list.cache"];
fetchedResultsController.delegate = self;
NSError *error;
BOOL success = [fetchedResultsController performFetch:&error];
if (!success) {
// Handle the error.
}
self.resultsController = fetchedResultsController;
[request release];
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.resultsController sections] count];
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[[self.resultsController sections] objectAtIndex:section] numberOfObjects];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0 || indexPath.row%2 == 0) {
UIColor *altCellColor = [UIColor colorWithWhite:1 alpha:0.1];
cell.backgroundColor = altCellColor;
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"NewsCell";
UILabel *mainLabel, *secondLabel;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake(40.0, 0.0, 280.0, 21.0)] autorelease];
mainLabel.tag = 1;
mainLabel.font = [UIFont systemFontOfSize:16.0];
mainLabel.textAlignment = UITextAlignmentLeft;
mainLabel.textColor = [UIColor blackColor];
mainLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:mainLabel];
mainLabel.backgroundColor = [UIColor clearColor];
secondLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 20.0, 280.0, 25.0)] autorelease];
secondLabel.tag = 2;
secondLabel.font = [UIFont systemFontOfSize:12.0];
secondLabel.textAlignment = UITextAlignmentRight;
secondLabel.textColor = [UIColor darkGrayColor];
secondLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:secondLabel];
secondLabel.backgroundColor = [UIColor clearColor];
} else {
mainLabel = (UILabel *)[cell.contentView viewWithTag:1];
secondLabel = (UILabel *)[cell.contentView viewWithTag:2];
}
News *news = [self.resultsController objectAtIndexPath:indexPath];
mainLabel.text = news.title;
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
secondLabel.text = [formatter stringFromDate:news.date];
return cell;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment