I’ve created a custom UITableViewCell class (SyncTableViewCell) and associated xib for it. I have also created a model (DataSyncController) for managing the underlying data for these cells. In my view controller I create and load the cells and link them to their data objects. I am using the NSNotificationCenter in my DataSyncController to post notes when various data changes in the object. I observe these notes in my SyncTableViewCell(s) and update the controls accordingly when the underlying data changes.
This is working quite well for me in most cases, but I have two issues. Here is the code in my model object, DataSyncController:
- (void)syncParts
{
WebService *service = [[WebService alloc] init];
SQLiteDatabase *database = [SQLiteDatabase database];
NSDate *startTime = [NSDate date];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerEnabledActivity" object:self userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerSyncActive" object:self userInfo:nil];
if (!lastSyncDate) { [self setLastSyncDate:[[database getLastPartSyncDate]stringByReplacingOccurrencesOfString:@" " withString:@"+"]]; }
if (!lastSyncDate) { lastSyncDate = @"1753-01-01"; }
currentStep = @"Connecting to Web Service..";
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerUpdatedStep" object:self userInfo:nil];
[service getPartsSinceDate:lastSyncDate
withResponseHandler:^(NSDictionary *requestResponse) {
MIMEtype = [NSString stringWithFormat:@"%@", [requestResponse valueForKey:@"MIMEType"]];
textEncoding = [NSString stringWithFormat:@"%@", [requestResponse valueForKey:@"textEncodingName"]];
fileName = [NSString stringWithFormat:@"%@", [requestResponse valueForKey:@"suggestedFilename"]];
dataSize = [NSNumber numberWithLongLong:(long long)[requestResponse valueForKey:@"expectedContentLength"]];
currentStep = [NSString stringWithFormat:@"Fetching %@ bytes of data from Web Service; last sync: %@", dataSize, lastSyncDate];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerUpdatedStep" object:self userInfo:nil];
}
withReceivedDataHandler:^(NSNumber *requestDataLength) {
if (dataSize > 0) {
progress = [NSNumber numberWithFloat:([requestDataLength floatValue] / [dataSize floatValue])];
NSLog(@"%f", [requestDataLength floatValue]);
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerUpdatedProgress" object:self userInfo:nil];
}
}
withCompletionHandler:^(NSArray *JSON) {
currentStep = [NSString stringWithFormat:@"Fetched %@ bytes of data in %f seconds; parsing JSON and modeling Parts..", [self progress], [[[NSDate alloc] init] timeIntervalSinceDate:startTime]];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerUpdatedStep" object:self userInfo:nil];
NSDate *startTime = [NSDate date];
NSMutableArray *partsArray = [[NSMutableArray alloc] init];
for (NSDictionary *dic in JSON) {
Part *currentPart = [[Part alloc] initWithPartNumber:[dic objectForKey:@"P"]
andDescription:[dic objectForKey:@"D"]
andWeight:[dic objectForKey:@"W"]
andPriceCategory:[dic objectForKey:@"C"]
andListPrice:[dic objectForKey:@"L"]];
[partsArray addObject:currentPart];
}
currentStep = [NSString stringWithFormat:@"JSON parsing and Parts modeling took %f seconds; performing database inserts..", [[[NSDate alloc] init] timeIntervalSinceDate:startTime]];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerUpdatedStep" object:self userInfo:nil];
startTime = [NSDate date];
NSString *SQLerror = [database insertPartsInBulk:partsArray];
if (SQLerror) {
progress = 0;
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerUpdatedProgress" object:self userInfo:nil];
currentStep = [NSString stringWithFormat:@"Error: %@", SQLerror];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerDisabledActivity" object:self userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerSyncError" object:self userInfo:nil];
}
else {
if ([partsArray count] == 0) {
progress = 0;
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerUpdatedProgress" object:self userInfo:nil];
currentStep = [NSString stringWithString:@"Data up-to-date!"];
}
else {
currentStep = [NSString stringWithFormat:@"Inserted %i Parts into database in %f seconds; sync' complete!", [partsArray count], [[[NSDate alloc] init] timeIntervalSinceDate:startTime]];
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerDisabledActivity" object:self userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerSyncComplete" object:self userInfo:nil];
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataSyncControllerUpdatedStep" object:self userInfo:nil];
}
];
}
The first issue is with UILabels on the cell getting updated. In all cases, when you see a ‘currentStep = @""’ followed by a “DataSyncControllerUpdatedStep” notification being posted, this code fires in my SyncTableViewCell:
- (void)updateCurrentStep:(NSNotification *)note
{
NSLog(@"Observed Update Current Step: %@", [dataSource currentStep]);
[[self currentStep] setText:[dataSource currentStep]];
}
Every time the notification is posted, I successfully observe it and see the NSLog output. The issue is, that the label is not being updated every time. (or maybe not being redrawn so I can see it…?)
Looking back at the - (void)syncParts code block, you will notice three block handlers being processed. I set “currentStep” and send the notification once prior to the blocks. This update shows successfully on the label. Again, in “withResponseHandler:”, I set “currentStep” and send the notification; again, the update shows successfully on the label. Finally, my problem arises in “withCompletionHandler:”. In this block, only the last update actually shows on the label. The first two just never actually update the label. Again, the NSLog statements show the correct text and that the update is being fired.
What am I missing?
My second, similar issue is with this block of code:
- (void)setIconToActive:(NSNotification *)note
{
NSLog(@"Animating");
iconState = 1;
//[icon setImage:[UIImage imageNamed:@"sync_active_0"]];
NSArray *images = [NSArray arrayWithObjects:
[UIImage imageNamed:@"sync_active_0.png"],
[UIImage imageNamed:@"sync_active_1.png"],
[UIImage imageNamed:@"sync_active_2.png"],
[UIImage imageNamed:@"sync_active_3.png"],
[UIImage imageNamed:@"sync_active_4.png"],
[UIImage imageNamed:@"sync_active_5.png"],
[UIImage imageNamed:@"sync_active_6.png"],
[UIImage imageNamed:@"sync_active_7.png"],
[UIImage imageNamed:@"sync_active_8.png"],
[UIImage imageNamed:@"sync_active_9.png"], nil];
[icon setAnimationImages:images];
[icon setAnimationDuration:1];
[icon setAnimationRepeatCount:0];
[icon startAnimating];
if ([icon isAnimating]) { NSLog(@"It IS Animating"); }
}
I am having the same issue here. The UIImageView (icon) does not change (animate) in the cell. Curiously, if I uncomment “[icon setImage:[UIImage imageNamed:@“sync_active_0”]];”, that does successfully update the UIImageView and it is visible in the cell.
Also, if you see anything glaringly asinine, please let me know. This is my first App.