7 Replies Latest reply: Feb 4, 2011 2:33 PM by nasholic
nasholic Level 1 Level 1 (0 points)
hello

I have a problem with the reloaddata method of uitableview. my tableview shows the values of a nsmanagedobject from my context. the object is updated from time to time and therefor I added an observer in my uitableview class how checks for changes and calls the reloaddata method if changes are made. now a strange behavior occurs since the device *does not show the updated values until I touch/scroll the display*. I googled a lot but I did not find a solution for this. any suggestions how this behavior occurs and can be corrected? thanks for your time. the code is the following..


#import "UAVDetailViewController.h"
#import "UAV.h"
#import "MapViewController.h"
#import "RightNavViewController.h"

@implementation UAVDetailViewController

@synthesize uavObject, tableDetailContents;

#pragma mark -
#pragma mark View lifecycle


- (void)viewDidLoad {
[super viewDidLoad];

//Get managedObjectContext from MapView
MapViewController *mapViewController;
if (UIUSER_INTERFACEIDIOM() == UIUserInterfaceIdiomPad) {
RightNavViewController *right = [[[self.splitViewController.viewControllers objectAtIndex:1] viewControllers] objectAtIndex:0];
mapViewController = right.mapViewController;

} else {
mapViewController = (MapViewController *)[[self.tabBarController viewControllers] objectAtIndex:0];
}

NSManagedObjectContext *context = mapViewController.managedObjectContext;

//register observer for context in notification center
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateTable:)
name:NSManagedObjectContextObjectsDidChangeNotification
object:context];


self.contentSizeForViewInPopover = CGSizeMake(320.0, 460.0);
self.navigationItem.title = [uavObject valueForKey:@"hostName"];

//for cells
self.tableDetailContents = [[NSArray alloc] initWithObjects:@"Hostname", @"IP Address", @"Status", @"Scenario", @"Longitude", @"Latitude", @"Height", @"Battery", @"Heading", @"Speed", nil];

}



- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}

//get uav from the context, assuming that the hostname won't change during flight
- (void)updateTable:(NSNotification *)theNotification {
NSManagedObjectContext *context = [theNotification object];
//check all updated objects if they are the uav object of this view controller
for(NSManagedObject *object in [[theNotification userInfo] objectForKey:NSUpdatedObjectsKey]) {
if ([object isMemberOfClass:[UAV class]]) {

NSManagedObject *toCheck = [context objectWithID:[object objectID]];

if ([[toCheck valueForKey:@"hostName"] isEqualToString:[self.uavObject valueForKey:@"hostName"]]) {
self.uavObject = toCheck;
[[self tableView] reloadData];
}
}
}
}


#pragma mark -
#pragma mark Table view data source

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


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [self.tableDetailContents count];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"UAVDetailCell";
NSUInteger row = [indexPath row];

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [self.tableDetailContents objectAtIndex:row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;

switch (row) {
case 0: //hostname
cell.detailTextLabel.text = [self.uavObject valueForKey:@"hostName"];
break;
case 1: //ip
cell.detailTextLabel.text = [self.uavObject valueForKey:@"ipAddress"];
break;
case 2: //status
if ([[self.uavObject valueForKey:@"state"] intValue] == 0) {
cell.detailTextLabel.text = @"UAVSTATEUNINITIALIZED";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 1) {
cell.detailTextLabel.text = @"UAVSTATEUNCONFIGURED";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 2) {
cell.detailTextLabel.text = @"UAVSTATE_AIRBORNE_AWAITINGPOS1";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 3) {
cell.detailTextLabel.text = @"UAVSTATE_AIRBORNE_AWAITING_FLIGHTDIRECTION";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 4) {
cell.detailTextLabel.text = @"UAVSTATE_AIRBORNE_AWAITINGPOS2";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 5) {
cell.detailTextLabel.text = @"UAVSTATE_AIRBORNE_REACHED_MAXDISTANCE";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 6) {
cell.detailTextLabel.text = @"UAVSTATE_AIRBORNE_FLYINGCENTER";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 7) {
cell.detailTextLabel.text = @"UAVSTATE_AIRBORNE_REACHEDCENTER";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 8) {
cell.detailTextLabel.text = @"UAVSTATE_FLYINGHOME";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 9) {
cell.detailTextLabel.text = @"UAVSTATEHOME";
} else if ([[self.uavObject valueForKey:@"state"] intValue] == 10) {
cell.detailTextLabel.text = @"UAVSTATEABORTED";
}

break;
case 3: //scenario
if ([[self.uavObject valueForKey:@"scenario"] intValue] == 0) {
cell.detailTextLabel.text = @"UAVSCENARIONONE";
} else if ([[self.uavObject valueForKey:@"scenario"] intValue] == 1) {
cell.detailTextLabel.text = @"UAVSCENARIOAIRBORNE";
} else if ([[self.uavObject valueForKey:@"scenario"] intValue] == 2) {
cell.detailTextLabel.text = @"UAVSCENARIOMULTIHOP";
} else if ([[self.uavObject valueForKey:@"scenario"] intValue] == 3) {
cell.detailTextLabel.text = @"UAVSCENARICOVERAGE";
}
break;
case 4: //longitude
cell.detailTextLabel.text = @"to do";
break;
case 5: //latitude
cell.detailTextLabel.text = @"to do";
break;
case 6: //height
cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[self.uavObject valueForKey:@"height"] intValue]];
break;
case 7: //battery
cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[self.uavObject valueForKey:@"battery"] intValue]];
break;
case 8: //heading
cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[self.uavObject valueForKey:@"heading"] intValue]];
break;
case 9: //speed
cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[self.uavObject valueForKey:@"speed"] intValue]];
break;

default:
break;
}

return cell;
}


#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];

// Relinquish ownership any cached data, images, etc. that aren't in use.
}

- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}


- (void)dealloc {
[tableDetailContents release];
[uavObject release];

[super dealloc];
}


@end

iOS 4, iPhone / iPad
  • 1. Re: tableview reloaddata - changes are not shown until display is touched
    RayNewbie Level 5 Level 5 (6,810 points)
    Hi Nasholic -
    nasholic wrote:
    the object is updated from time to time and therefor I added an observer in my uitableview class how checks for changes and calls the reloaddata method if changes are made. now a strange behavior occurs since the device *does not show the updated values until I touch/scroll the display*.


    //get uav from the context, assuming that the hostname won't change during flight
    - (void)updateTable:(NSNotification *)theNotification {
    NSManagedObjectContext *context = [theNotification object];
    NSLog(@"%s: context=%@", _func_, context);

    //check all updated objects if they are the uav object of this view controller
    for(NSManagedObject *object in [[theNotification userInfo] objectForKey:NSUpdatedObjectsKey]) {
    if ([object isMemberOfClass:[UAV class]]) {

    NSManagedObject *toCheck = [context objectWithID:[object objectID]];

    NSLog(@"--> toCheck=%@ toCheck.hostName=%@", toCheck, [toCheck valueForKey:@"hostName"]);
    NSLog(@"--> self.uavObject=%@ self.uavObject.hostName=%@", self.uavObject, [self.uavObject valueForKey:@"hostName"]);

    if ([[toCheck valueForKey:@"hostName"] isEqualToString:[self.uavObject valueForKey:@"hostName"]]) {
    NSLog(@"--> Should Reload Data Now <--");

    self.uavObject = toCheck;
    [[self tableView] reloadData];
    }
    }
    }
    }

    Since reloadData is only called in one place, I think that's where we need to look. I would add some logging to make sure reloadData is being sent when you expect. If that's not helpful, please post the log produced by running the above. - Ray
  • 2. Re: tableview reloaddata - changes are not shown until display is touched
    nasholic Level 1 Level 1 (0 points)
    hi ray

    thanks for your response, I'm working on an universal app for monitoring and controlling small unmaned aerial vehicules. those uavs send me notification messages with udp about their status. as soon as the iPad/iPhone receives a notification message, the status of the uav is written in the sqlite database. then the observer recognises the changes in the context and calls the reloaddata method, but still I don't see the actual values until I touch/scroll the display. If I don't touch the display the old values remain, even if I received dozens of notification messages and the reloaddata function was called several times. I've added your nslog messages to the code and the output was


    2011-02-02 13:42:31.323 RemoteControl[6851:7217] notificationsocket established: 8
    2011-02-02 13:42:31.324 RemoteControl[6851:7217] notificationlistener: waiting to recvfrom...
    2011-02-02 13:42:33.185 RemoteControl[6851:7217] received notification: 129 bytes from socket: #nWVBn=HRpp=FUwmY==K`zV{M=w]A>=]==nUVn==Jrp=EMzmY===A?=mMB>`[VYM@x[ym?c=eE===C>MM@=]B^VDFfUSumJ_viXsJ^X=@plr||m==IPaoH`AsK?u=cq
    2011-02-02 13:42:33.188 RemoteControl[6851:7217] strlen(buf): 129
    2011-02-02 13:42:33.197 RemoteControl[6851:7217] notificationlistener: got packet from
    2011-02-02 13:42:33.198 RemoteControl[6851:7217] notificationlistener: packet is 129 bytes long
    2011-02-02 13:42:33.201 RemoteControl[6851:7217] -[UAVDetailViewController updateTable:]: context=<NSManagedObjectContext: 0x15c6b0>
    2011-02-02 13:42:33.207 RemoteControl[6851:7217] --> toCheck=<UAV: 0x1b1c70> (entity: UAV; id: 0x1792b0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/UAV/p1> ; data: {
    battery = 103;
    heading = 228;
    height = 65000;
    hostName = "adrian06.local";
    ipAddress = "192.168.1.1";
    locationHistory = (
    "0x1722d0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p3>",
    "0x1613a0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p2>",
    "0x18f0f0 <x-coredata:///Location/t5170414F-01D1-4278-BB3D-717B0A09442C11>",
    "0x19c520 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p1>",
    "0x186c30 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p5>",
    "0x1b3410 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p6>",
    "0x15b790 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p4>",
    "0x1a0000 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p7>"
    );
    scenario = 1;
    speed = 490;
    state = 2;
    }) toCheck.hostName=adrian06.local
    2011-02-02 13:42:33.219 RemoteControl[6851:7217] --> self.uavObject=<UAV: 0x1b1c70> (entity: UAV; id: 0x1792b0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/UAV/p1> ; data: {
    battery = 103;
    heading = 228;
    height = 65000;
    hostName = "adrian06.local";
    ipAddress = "192.168.1.1";
    locationHistory = (
    "0x1722d0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p3>",
    "0x1613a0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p2>",
    "0x18f0f0 <x-coredata:///Location/t5170414F-01D1-4278-BB3D-717B0A09442C11>",
    "0x19c520 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p1>",
    "0x186c30 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p5>",
    "0x1b3410 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p6>",
    "0x15b790 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p4>",
    "0x1a0000 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p7>"
    );
    scenario = 1;
    speed = 490;
    state = 2;
    }) self.uavObject.hostName=adrian06.local
    2011-02-02 13:42:33.225 RemoteControl[6851:7217] --> Should Reload Data Now <--
    2011-02-02 13:42:33.396 RemoteControl[6851:7217] notificationsocket established: 8
    2011-02-02 13:42:33.400 RemoteControl[6851:7217] notificationlistener: waiting to recvfrom...
    2011-02-02 13:42:35.187 RemoteControl[6851:7217] received notification: 129 bytes from socket: #ngefn=Grnp=EMzmY==J?AU|U=v]=>=]==nUVn==Jrp=EMzmY===A?=mMB>`[VYM@x[ym?c=eE===C>MM@=]B^VDFfUSumJ_viXsJ^X=@plr||m==IPaoH`AsK?u=cs
    2011-02-02 13:42:35.189 RemoteControl[6851:7217] strlen(buf): 129
    2011-02-02 13:42:35.191 RemoteControl[6851:7217] notificationlistener: got packet from
    2011-02-02 13:42:35.192 RemoteControl[6851:7217] notificationlistener: packet is 129 bytes long
    2011-02-02 13:42:35.198 RemoteControl[6851:7217] -[UAVDetailViewController updateTable:]: context=<NSManagedObjectContext: 0x15c6b0>
    2011-02-02 13:42:35.201 RemoteControl[6851:7217] --> toCheck=<UAV: 0x1b1c70> (entity: UAV; id: 0x1792b0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/UAV/p1> ; data: {
    battery = 99;
    heading = 246;
    height = 34000;
    hostName = "adrian06.local";
    ipAddress = "192.168.1.1";
    locationHistory = (
    "0x1722d0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p3>",
    "0x1613a0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p2>",
    "0x17e1b0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p8>",
    "0x19c520 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p1>",
    "0x186c30 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p5>",
    "0x1b3410 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p6>",
    "0x15b790 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p4>",
    "0x1a1cb0 <x-coredata:///Location/t5170414F-01D1-4278-BB3D-717B0A09442C12>",
    "0x1a0000 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p7>"
    );
    scenario = 1;
    speed = 230;
    state = 2;
    }) toCheck.hostName=adrian06.local
    2011-02-02 13:42:35.212 RemoteControl[6851:7217] --> self.uavObject=<UAV: 0x1b1c70> (entity: UAV; id: 0x1792b0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/UAV/p1> ; data: {
    battery = 99;
    heading = 246;
    height = 34000;
    hostName = "adrian06.local";
    ipAddress = "192.168.1.1";
    locationHistory = (
    "0x1722d0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p3>",
    "0x1613a0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p2>",
    "0x17e1b0 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p8>",
    "0x19c520 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p1>",
    "0x186c30 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p5>",
    "0x1b3410 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p6>",
    "0x15b790 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p4>",
    "0x1a1cb0 <x-coredata:///Location/t5170414F-01D1-4278-BB3D-717B0A09442C12>",
    "0x1a0000 <x-coredata://05D9E0C1-D3BE-4D13-BBAD-0BABF4C927C3/Location/p7>"
    );
    scenario = 1;
    speed = 230;
    state = 2;
    }) self.uavObject.hostName=adrian06.local
    2011-02-02 13:42:35.218 RemoteControl[6851:7217] --> Should Reload Data Now <--
  • 3. Re: tableview reloaddata - changes are not shown until display is touched
    xnav Level 5 Level 5 (6,630 points)
    I don't see where

    - (void)updateTable:(NSNotification *)theNotification {

    is updating tableDetailContents, the array which actually backs the tableview?
  • 4. Re: tableview reloaddata - changes are not shown until display is touched
    nasholic Level 1 Level 1 (0 points)
    xnav wrote:
    I don't see where

    - (void)updateTable:(NSNotification *)theNotification {

    is updating tableDetailContents, the array which actually backs the tableview?


    hi xnav
    the tableDetailContents array is static, since the table should always show the property names like ip, hostname etc. of the uav object, but the cell.detailTextLabel.text should change and should show the actual values of those properties.
  • 5. Re: tableview reloaddata - changes are not shown until display is touched
    xnav Level 5 Level 5 (6,630 points)
    Maybe you have to refetch as in this [thread|http://discussions.apple.com/thread.jspa?threadID=2733014]?
  • 6. Re: tableview reloaddata - changes are not shown until display is touched
    xnav Level 5 Level 5 (6,630 points)

    if ([[toCheck valueForKey:@"hostName"] isEqualToString:[self.uavObject valueForKey:@"hostName"]]) {
    self.uavObject = toCheck;
    [[self tableView] reloadData];

    Check with a breakpoint if [self tableView] is returning nil.
  • 7. Re: tableview reloaddata - changes are not shown until display is touched
    nasholic Level 1 Level 1 (0 points)
    I found a solution, I call

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


    instead of


    [[self tableView] reloadData]


    now it get updated instantly.. thanks for the help