NSTableView with NSArray and C-array question

  • Hello everyone,

    My first post here, I hope it fits in this list...

    I'm porting a C-based data acquistion program running in Mac OS X
    Terminal.app to Cocoa.

    The C-based data acq. program scans 16 channels from a Keithley 2700
    (with 7700 multiplexer) Multimeter every 5 seconds via USB-to-Serial
    Port.
    The multimeter spits out a string which then I convert to 'double'
    float values in a C-array. This works great since a couple of months.

    The main part of it, acquiring data every 5 sec works fine also in
    Cocoa (using NSTimer etc.)

    However displaying the data with NSTableView gives me more headaches...

    [1]. Should I use only *one* NSMutableArray or *multiple*
    NSMutableArray for the channels ?
    My understanding is that NSTableView needs an NSArray to display the
    data row-wise, so I can't use the C-array directly....

    (Since the array grows up every 5 seconds....(so for one day we get
    about: 86400sec / 5sec = 17280 lines).
    So for 16 channels: (16*17280) = 276480 data values for a full
    day...this will make a really big array, IMHO.)

    [2]. How to simplify the output of data with method (id)tableView:
    (NSTableView *)tableView objectValueForTableColumn....?

    I've tried using this for the 16 columns:

    if ( [[Column identifier] isEqualToString:@"1"])
    {
      return  [array objectAtIndex:Row];
    }
    etc.

    This works less or more but every row gets the same value as the row
    before!!! It drives me nuts!
    Does someone have any suggestions with [array valueForKey....] ?

    Any suggestions will be greatly appreciated.

    Cheers,

    Gilles Celli
  • Unless you are using bindings, NSTableView doesn't need an NSArray. It
    is often just convenient to use them because you're often times
    displaying a collection of NSObjects (such as NSString or NSNumber).

    - (int)numberOfRowsInTableView:(NSTableView *)aTableView;

    - (id)tableView:(NSTableView *)aTableView
    objectValueForTableColumn:(NSTableColumn *)aTableColumn
    row:(int)rowIndex;

    Neither of these reference any NSArray. the objectValueForTableColumn
    does require an object be returned, but that could be supplied with
    something like [NSString stringWithFormat:@"%f",myArray[rowIndex]];

    There is nothing that stops you from using standard C-arrays. It
    sounds like doing so would dramatically reduce overhead (otherwise you
    have to create an NSNumber object for each value you want to add to
    the NSArray, which only deals with NSObjects).

    Mark Munz

    On 10/12/06, Gilles Celli <gilles.celli...> wrote:
    > Hello everyone,
    >
    > My first post here, I hope it fits in this list...
    >
    > I'm porting a C-based data acquistion program running in Mac OS X
    > Terminal.app to Cocoa.
    >
    > The C-based data acq. program scans 16 channels from a Keithley 2700
    > (with 7700 multiplexer) Multimeter every 5 seconds via USB-to-Serial
    > Port.
    > The multimeter spits out a string which then I convert to 'double'
    > float values in a C-array. This works great since a couple of months.
    >
    > The main part of it, acquiring data every 5 sec works fine also in
    > Cocoa (using NSTimer etc.)
    >
    > However displaying the data with NSTableView gives me more headaches...
    >
    > [1]. Should I use only *one* NSMutableArray or *multiple*
    > NSMutableArray for the channels ?
    > My understanding is that NSTableView needs an NSArray to display the
    > data row-wise, so I can't use the C-array directly....
    >
    > (Since the array grows up every 5 seconds....(so for one day we get
    > about: 86400sec / 5sec = 17280 lines).
    > So for 16 channels: (16*17280) = 276480 data values for a full
    > day...this will make a really big array, IMHO.)
    >
    > [2]. How to simplify the output of data with method (id)tableView:
    > (NSTableView *)tableView objectValueForTableColumn....?
    >
    > I've tried using this for the 16 columns:
    >
    > if ( [[Column identifier] isEqualToString:@"1"])
    > {
    > return  [array objectAtIndex:Row];
    > }
    > etc.
    >
    > This works less or more but every row gets the same value as the row
    > before!!! It drives me nuts!
    > Does someone have any suggestions with [array valueForKey....] ?
    >
    > Any suggestions will be greatly appreciated.

    --
    Mark Munz
    unmarked software
    http://www.unmarked.com/
  • On Oct 12, 2006, at 12:41 PM, Mark Munz wrote:
    > Unless you are using bindings, NSTableView doesn't need an NSArray. It
    > is often just convenient to use them because you're often times
    > displaying a collection of NSObjects (such as NSString or NSNumber).

    And even with bindings, you don't need to use an NSArray - just an
    NSArrayController, which may be wrapping whatever "ordered list"
    implementation you like.

    Daniel
  • Ok thanks. I will try that tomorrow to only add the C-Array to the
    NSTableView.
    Stay tuned!

    Gilles Celli

    On Oct 12, 2006, at 6:41 PM, Mark Munz wrote:

    > Unless you are using bindings, NSTableView doesn't need an NSArray. It
    > is often just convenient to use them because you're often times
    > displaying a collection of NSObjects (such as NSString or NSNumber).
    >
    > - (int)numberOfRowsInTableView:(NSTableView *)aTableView;
    >
    > - (id)tableView:(NSTableView *)aTableView
    > objectValueForTableColumn:(NSTableColumn *)aTableColumn
    > row:(int)rowIndex;
    >
    > Neither of these reference any NSArray. the objectValueForTableColumn
    > does require an object be returned, but that could be supplied with
    > something like [NSString stringWithFormat:@"%f",myArray[rowIndex]];
    >
    > There is nothing that stops you from using standard C-arrays. It
    > sounds like doing so would dramatically reduce overhead (otherwise you
    > have to create an NSNumber object for each value you want to add to
    > the NSArray, which only deals with NSObjects).
    >
    > Mark Munz
    >
    > On 10/12/06, Gilles Celli <gilles.celli...> wrote:
    >> Hello everyone,
    >>
    >> My first post here, I hope it fits in this list...
    >>
    >> I'm porting a C-based data acquistion program running in Mac OS X
    >> Terminal.app to Cocoa.
    >>
    >> The C-based data acq. program scans 16 channels from a Keithley 2700
    >> (with 7700 multiplexer) Multimeter every 5 seconds via USB-to-Serial
    >> Port.
    >> The multimeter spits out a string which then I convert to 'double'
    >> float values in a C-array. This works great since a couple of months.
    >>
    >> The main part of it, acquiring data every 5 sec works fine also in
    >> Cocoa (using NSTimer etc.)
    >>
    >> However displaying the data with NSTableView gives me more
    >> headaches...
    >>
    >> [1]. Should I use only *one* NSMutableArray or *multiple*
    >> NSMutableArray for the channels ?
    >> My understanding is that NSTableView needs an NSArray to display the
    >> data row-wise, so I can't use the C-array directly....
    >>
    >> (Since the array grows up every 5 seconds....(so for one day we get
    >> about: 86400sec / 5sec = 17280 lines).
    >> So for 16 channels: (16*17280) = 276480 data values for a full
    >> day...this will make a really big array, IMHO.)
    >>
    >> [2]. How to simplify the output of data with method (id)tableView:
    >> (NSTableView *)tableView objectValueForTableColumn....?
    >>
    >> I've tried using this for the 16 columns:
    >>
    >> if ( [[Column identifier] isEqualToString:@"1"])
    >> {
    >> return  [array objectAtIndex:Row];
    >> }
    >> etc.
    >>
    >> This works less or more but every row gets the same value as the row
    >> before!!! It drives me nuts!
    >> Does someone have any suggestions with [array valueForKey....] ?
    >>
    >> Any suggestions will be greatly appreciated.
    >
    > --
    > Mark Munz
    > unmarked software
    > http://www.unmarked.com/
    >
  • I've figured out how to display only the C-array in NSTableView,
    however i've getting for every Row the same value, e.g for 3 rows and
    1 channel:

    (remember updates every 5 seconds via reloadData the NSTableView)

    Channel1
    -4.555
    -4.555 => from previous row :-(
    -4.555 => from previous row :-(

    For  method numberOfRowsInTableView I've only a counter which gets
    incremented after every reloadData.

    - (int) numberOfRowsInTableView:(NSTableView *)tableView
    {
    return counter;
    }

    Any help / suggestion ?

    Thanks

    Gilles Celli

    On Oct 12, 2006, at 6:41 PM, Mark Munz wrote:

    > Unless you are using bindings, NSTableView doesn't need an NSArray. It
    > is often just convenient to use them because you're often times
    > displaying a collection of NSObjects (such as NSString or NSNumber).
    >
    > - (int)numberOfRowsInTableView:(NSTableView *)aTableView;
    >
    > - (id)tableView:(NSTableView *)aTableView
    > objectValueForTableColumn:(NSTableColumn *)aTableColumn
    > row:(int)rowIndex;
    >
    > Neither of these reference any NSArray. the objectValueForTableColumn
    > does require an object be returned, but that could be supplied with
    > something like [NSString stringWithFormat:@"%f",myArray[rowIndex]];
    >
    > There is nothing that stops you from using standard C-arrays. It
    > sounds like doing so would dramatically reduce overhead (otherwise you
    > have to create an NSNumber object for each value you want to add to
    > the NSArray, which only deals with NSObjects).
    >
    > Mark Munz
    >
    > On 10/12/06, Gilles Celli <gilles.celli...> wrote:
    >> Hello everyone,
    >>
    >> My first post here, I hope it fits in this list...
    >>
    >> I'm porting a C-based data acquistion program running in Mac OS X
    >> Terminal.app to Cocoa.
    >>
    >> The C-based data acq. program scans 16 channels from a Keithley 2700
    >> (with 7700 multiplexer) Multimeter every 5 seconds via USB-to-Serial
    >> Port.
    >> The multimeter spits out a string which then I convert to 'double'
    >> float values in a C-array. This works great since a couple of months.
    >>
    >> The main part of it, acquiring data every 5 sec works fine also in
    >> Cocoa (using NSTimer etc.)
    >>
    >> However displaying the data with NSTableView gives me more
    >> headaches...
    >>
    >> [1]. Should I use only *one* NSMutableArray or *multiple*
    >> NSMutableArray for the channels ?
    >> My understanding is that NSTableView needs an NSArray to display the
    >> data row-wise, so I can't use the C-array directly....
    >>
    >> (Since the array grows up every 5 seconds....(so for one day we get
    >> about: 86400sec / 5sec = 17280 lines).
    >> So for 16 channels: (16*17280) = 276480 data values for a full
    >> day...this will make a really big array, IMHO.)
    >>
    >> [2]. How to simplify the output of data with method (id)tableView:
    >> (NSTableView *)tableView objectValueForTableColumn....?
    >>
    >> I've tried using this for the 16 columns:
    >>
    >> if ( [[Column identifier] isEqualToString:@"1"])
    >> {
    >> return  [array objectAtIndex:Row];
    >> }
    >> etc.
    >>
    >> This works less or more but every row gets the same value as the row
    >> before!!! It drives me nuts!
    >> Does someone have any suggestions with [array valueForKey....] ?
    >>
    >> Any suggestions will be greatly appreciated.
    >
    > --
    > Mark Munz
    > unmarked software
    > http://www.unmarked.com/
    >
  • On Oct 13, 2006, at 11:10 AM, Gilles Celli wrote:

    > I've figured out how to display only the C-array in NSTableView,
    > however i've getting for every Row the same value, e.g for 3 rows
    > and 1 channel:
    >
    > (remember updates every 5 seconds via reloadData the NSTableView)
    >
    > Channel1
    > -4.555
    > -4.555 => from previous row :-(
    > -4.555 => from previous row :-(
    >
    > For  method numberOfRowsInTableView I've only a counter which gets
    > incremented after every reloadData.
    >
    > - (int) numberOfRowsInTableView:(NSTableView *)tableView
    > {
    > return counter;
    > }
    >
    > Any help / suggestion ?

    Re-post your -objectValueForTableColumn:rowIndex method, please. The -
    numberOfRowsInTableView: data-source method alone isn't of much use
    in chasing down the problem.

    GZ
  • Here my:

    - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:
    (NSTableColumn *)Column row:(int)Row

    if ( [[Column identifier] isEqualToString:@"1"])
    {
      return [NSNumber numberWithDouble:[k2700 channel:0]];
    }
    else if ( [[Column identifier] isEqualToString:@"2"])
    {
      return [NSNumber numberWithDouble:[k2700 channel:1]];
    }
    else if ( [[Column identifier] isEqualToString:@"3"])
    {
      return [NSNumber numberWithDouble:[k2700 channel:2]];
    }
    .....
    ....
    }

    On Oct 13, 2006, at 5:15 PM, Glenn Zelniker wrote:

    >
    > On Oct 13, 2006, at 11:10 AM, Gilles Celli wrote:
    >
    >> I've figured out how to display only the C-array in NSTableView,
    >> however i've getting for every Row the same value, e.g for 3 rows
    >> and 1 channel:
    >>
    >> (remember updates every 5 seconds via reloadData the NSTableView)
    >>
    >> Channel1
    >> -4.555
    >> -4.555 => from previous row :-(
    >> -4.555 => from previous row :-(
    >>
    >> For  method numberOfRowsInTableView I've only a counter which gets
    >> incremented after every reloadData.
    >>
    >> - (int) numberOfRowsInTableView:(NSTableView *)tableView
    >> {
    >> return counter;
    >> }
    >>
    >> Any help / suggestion ?
    >
    > Re-post your -objectValueForTableColumn:rowIndex method, please.
    > The -numberOfRowsInTableView: data-source method alone isn't of
    > much use in chasing down the problem.
    >
    > GZ
    >
    >
  • On Oct 13, 2006, at 11:20 AM, Gilles Celli wrote:

    > Here my:
    >
    > - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:
    > (NSTableColumn *)Column row:(int)Row
    >
    > if ( [[Column identifier] isEqualToString:@"1"])
    > {
    > return [NSNumber numberWithDouble:[k2700 channel:0]];
    > }
    > else if ( [[Column identifier] isEqualToString:@"2"])
    > {
    > return [NSNumber numberWithDouble:[k2700 channel:1]];
    > }
    > else if ( [[Column identifier] isEqualToString:@"3"])
    > {
    > return [NSNumber numberWithDouble:[k2700 channel:2]];
    > }
    > .....
    > ....
    > }

    You're ignoring the value of Row. Remember -- this is a data-source
    method, which means your code is being asked to provide the object
    value for the indicated table column at the indicated row. The code
    above returns the same value for each column *regardless* of the
    table row. I'm assuming that you're trying to display in your table
    the data for a number of sensors (indicated by a column) at different
    points in time (indicated by row position). Is this correct?

    GZ
  • > I'm assuming that you're trying to display in your table the data
    > for a number of sensors (indicated by a column) at different points
    > in time (indicated by row position). Is this correct?
    yes right! In fact voltage values for a 16 channel multimeter. The
    NSTableView columns have numerical identifiers (1-16) and with Date/
    Time (but not implemented yet...).

    On Oct 13, 2006, at 5:27 PM, Glenn Zelniker wrote:

    >
    > On Oct 13, 2006, at 11:20 AM, Gilles Celli wrote:
    >
    >> Here my:
    >>
    >> - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:
    >> (NSTableColumn *)Column row:(int)Row
    >>
    >> if ( [[Column identifier] isEqualToString:@"1"])
    >> {
    >> return [NSNumber numberWithDouble:[k2700 channel:0]];
    >> }
    >> else if ( [[Column identifier] isEqualToString:@"2"])
    >> {
    >> return [NSNumber numberWithDouble:[k2700 channel:1]];
    >> }
    >> else if ( [[Column identifier] isEqualToString:@"3"])
    >> {
    >> return [NSNumber numberWithDouble:[k2700 channel:2]];
    >> }
    >> .....
    >> ....
    >> }
    >
    > You're ignoring the value of Row. Remember -- this is a data-source
    > method, which means your code is being asked to provide the object
    > value for the indicated table column at the indicated row. The code
    > above returns the same value for each column *regardless* of the
    > table row. I'm assuming that you're trying to display in your table
    > the data for a number of sensors (indicated by a column) at
    > different points in time (indicated by row position). Is this correct?
    >
    > GZ
    >
    >
  • On Oct 13, 2006, at 11:34 AM, Gilles Celli wrote:

    >> I'm assuming that you're trying to display in your table the data
    >> for a number of sensors (indicated by a column) at different
    >> points in time (indicated by row position). Is this correct?
    > yes right! In fact voltage values for a 16 channel multimeter. The
    > NSTableView columns have numerical identifiers (1-16) and with Date/
    > Time (but not implemented yet...).

    Until you implement the Date/Time and map it to a row index, you're
    not going to see anything meaningful in your table.

    GZ
  • On Oct 13, 2006, at 5:39 PM, Glenn Zelniker wrote:

    >
    > On Oct 13, 2006, at 11:34 AM, Gilles Celli wrote:
    >
    >>> I'm assuming that you're trying to display in your table the data
    >>> for a number of sensors (indicated by a column) at different
    >>> points in time (indicated by row position). Is this correct?
    >> yes right! In fact voltage values for a 16 channel multimeter. The
    >> NSTableView columns have numerical identifiers (1-16) and with
    >> Date/Time (but not implemented yet...).
    >
    > Until you implement the Date/Time and map it to a row index, you're
    > not going to see anything meaningful in your table.
    >
    > GZ
    >
    so you think I that I should return a NSCalendarDate in method -(int)
    numberOfRowsInTableView... ?
  • On Oct 13, 2006, at 11:43 AM, Gilles Celli wrote:

    >> Until you implement the Date/Time and map it to a row index,
    >> you're not going to see anything meaningful in your table.
    >>
    >> GZ
    >>
    > so you think I that I should return a NSCalendarDate in method -
    > (int)numberOfRowsInTableView... ?

    Absolutely not. You should return an int representing however many
    rows are supposed to be in your table. What you really need to do,
    however, is find a way to parameterize your data in a meaningful way
    that corresponds to the time-stamps for your collection of samples.

    Do you intend to keep adding new samples to the bottom of the table,
    or do you only maintain a fixed number of rows, with the oldest
    samples "disappearing off the top" of the table as new ones are added
    to the bottom?

    GZ
  • On Oct 13, 2006, at 5:50 PM, Glenn Zelniker wrote:

    >
    > On Oct 13, 2006, at 11:43 AM, Gilles Celli wrote:
    >
    >>> Until you implement the Date/Time and map it to a row index,
    >>> you're not going to see anything meaningful in your table.
    >>>
    >>> GZ
    >>>
    >> so you think I that I should return a NSCalendarDate in method -
    >> (int)numberOfRowsInTableView... ?
    >
    > Absolutely not. You should return an int representing however many
    > rows are supposed to be in your table. What you really need to do,
    > however, is find a way to parameterize your data in a meaningful
    > way that corresponds to the time-stamps for your collection of
    > samples.
    >
    > Do you intend to keep adding new samples to the bottom of the
    > table, or do you only maintain a fixed number of rows, with the
    > oldest samples "disappearing off the top" of the table as new ones
    > are added to the bottom?
    >
    > GZ
    Yes adding new samples to the bottom of the table, then deleting all
    the rows at midnight... Knowing that data is acquired every 5 seconds
    we get about
    17240 rows for 24hours...
  • > so you think I that I should return a NSCalendarDate in method -(int)
    > numberOfRowsInTableView... ?

    No, don't do that!

    Right now it seems like you're not storing up the data in memory
    anywhere, and expecting NSTableView to keep track of it for you.
    NSTableView doesn't work like that.  You have to explicitly tell it
    what data goes in what row every time it asks you.  That's just how
    the delegate methods work.

    So, if you want to go the delegate route (your other choice is to use
    Cocoa bindings), you'll need to keep track of all of the past samples
    and what row they were in.  A simple way to do that might be to use an
    NSMutableArray, and call -addObject: each time you get a new sample:

    -(void) addSample:(id)sample
    {
        // _dataArray is an instance of NSMutableArray
        [_dataArray addObject:sample];
    }

    -(int) numberOfRowsInTableView
    {
        return [_dataArray count];
    }

    -(id) tableView:(NSTableView *)tableView objectValueForTableColumn:
    (NSTableColumn *)Column row:(int)Row
    {
        id theData = [_dataArray objectAtIndex:Row];
        // return the proper column of theData
    }

    This could be made much more efficient, especially for large datasets,
    but that's the gist of it.

    --
    Stephen Deken
    <stephen.deken...>
  • hmm, ok... that's what I tried with NSArray but I get exactly the
    same problem: every row has the same value ?
    and someone before wrote that there's too much overhead to add the
    values to an NSArray (with more than 17000 rows...).

    I will look (again) this week-end to find this out...drives me nuts...

    On Oct 13, 2006, at 5:57 PM, Stephen Deken wrote:

    >> so you think I that I should return a NSCalendarDate in method -(int)
    >> numberOfRowsInTableView... ?
    >
    > No, don't do that!
    >
    > Right now it seems like you're not storing up the data in memory
    > anywhere, and expecting NSTableView to keep track of it for you.
    > NSTableView doesn't work like that.  You have to explicitly tell it
    > what data goes in what row every time it asks you.  That's just how
    > the delegate methods work.
    >
    > So, if you want to go the delegate route (your other choice is to use
    > Cocoa bindings), you'll need to keep track of all of the past samples
    > and what row they were in.  A simple way to do that might be to use an
    > NSMutableArray, and call -addObject: each time you get a new sample:
    >
    > -(void) addSample:(id)sample
    > {
    > // _dataArray is an instance of NSMutableArray
    > [_dataArray addObject:sample];
    > }
    >
    > -(int) numberOfRowsInTableView
    > {
    > return [_dataArray count];
    > }
    >
    > -(id) tableView:(NSTableView *)tableView objectValueForTableColumn:
    > (NSTableColumn *)Column row:(int)Row
    > {
    > id theData = [_dataArray objectAtIndex:Row];
    > // return the proper column of theData
    > }
    >
    > This could be made much more efficient, especially for large datasets,
    > but that's the gist of it.
    >
    > --
    > Stephen Deken
    > <stephen.deken...>
    >
  • On Oct 13, 2006, at 11:43 AM, Gilles Celli wrote:

    >
    > On Oct 13, 2006, at 5:39 PM, Glenn Zelniker wrote:
    >
    >>
    >> On Oct 13, 2006, at 11:34 AM, Gilles Celli wrote:
    >>
    >>>> I'm assuming that you're trying to display in your table the
    >>>> data for a number of sensors (indicated by a column) at
    >>>> different points in time (indicated by row position). Is this
    >>>> correct?
    >>> yes right! In fact voltage values for a 16 channel multimeter.
    >>> The NSTableView columns have numerical identifiers (1-16) and
    >>> with Date/Time (but not implemented yet...).
    >>
    >> Until you implement the Date/Time and map it to a row index,
    >> you're not going to see anything meaningful in your table.
    >>
    >> GZ
    >>
    > so you think I that I should return a NSCalendarDate in method -
    > (int)numberOfRowsInTableView... ?

    No, that wouldn't do anything useful.

    (Warning, code typed in mail.)

    Say that you place each sample acquired from the digital multimeter
    into a C struct.  (I seem to recall that you were asking about
    putting data stored in a C array into a table view, so I'll use
    vanilla C rather than objects.)

    #include <sys/time.h>

    struct sample {
        struct timeval tv;    /* via gettimeofday(2), for example, or use
    NSDate */
        double channels[15];
    };

    struct sample samples[20000];    /* or dynamically allocate */
    int nsamples;

    Then your table view data source methods might look something like this:

    - (int) numberOfRowsInTableView:(NSTableView *)tableView
    {
        return nsamples;
    }

    - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:
    (NSTableColumn *)Column row:(int)Row
    {
        struct sample s = samples[Row];

        if ([[Column identifier] isEqualToString:@"1"])
            return [NSNumber numberWithDoublle:s.channels[0]];
        else if ([[Column identifier] isEqualToString:@"2"])
            return [NSNumber numberWithDoublle:s.channels[1]];
        etc.

    }

    You could also put the timestamps in the table view by adding another
    column with an identifier of "timestamp", and formatting the struct
    timeval appropriately.
  • > and someone before wrote that there's too much overhead to add the
    > values to an NSArray (with more than 17000 rows...).

    Yes, that's true.  In that case you're better off keeping track of the
    data in straight C structs to eliminate the overhead.  You already
    know the maximum number of rows you'll have, so you can preallocate
    pointers, and then fill it up as you go.  Code below was typed inline,
    and was not run through any sort of checking.

    --sjd;

    struct my_data
    {
        float data_points[16];
    } my_data;

    struct my_array
    {
        my_data *data[1800];
        int num_valid_rows;
    } my_array;

    @interface MyTableViewDelegate : NSObject
    {
        my_array my_array_instance;
    }

    @implementation MyTableViewDelegate

    -(int) numberOfRowsInTableView:(id)v
    {
        return my_array_instance.num_valid_rows;
    }

    -(id) tableView:(id)t objectValueForTableColumn:...
    {
        // Add bounds and validity checks here!
        return my_array_instance.data[row_num]->data_points[col_num];
    }
  • Hello,

    Hope someone remembers my problem I had with NSTableView....
    I've been quite busy these last days coding and I got finally a
    working NSTableView with acquired data from a Keithley Multimeter
    with 16 channels (via USB port).

    For speed and memory efficiency I'm just using plain old C-structure
    instead of NSArray as you guys suggested here on the mailing-list.
    This works great!!

    However I have the following problem:

    The timevalue of the acquisiton in the NSTableview gets updated but
    every row gets the same value... the channel values are correct.

    Remember that the acquisition is every 5seconds....making an NSLog of
    the time structure correctly spits out the time.

    E.g in NSTableView:

    Time        |  Chan1  | Chan 2 | ...
    14:51:05    |  0.912     |  0.122    |
    14:51:05    |  1.331    |  0.811    | <= time bug, should be +5 seconds :-(
    14:51:05    |  1.331    |  0.811    | <= time bug, should be +10 seconds :-(

    Here's my C-structure declared in my class:

    struct keithley_struct {

      // Normal time structure
      struct tm *tm_utc;

      double channel[MAX_NBR_OF_CHANNELS];

    } k2700_data[MAX_ACQ_DATA_PER_DAY];

    And here from my Controller the tableView code:

    - (int) numberOfRowsInTableView:(NSTableView *)tableView
    {
    return [k2700 currentRow];
    }

    - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:
    (NSTableColumn *)Column row:(int)Row
    {
    int i=0;
    NSString *identifier = [Column identifier];

    struct keithley_struct *k2700_str;

    k2700_str = [k2700 k2700_data];


    for (i=0 ; i <= NBR_OF_CHANNELS; i++)
    {
      if ( [identifier isEqualToString:@"time"])
    {
      return [NSNumber numberWithInt:k2700_str[Row].tm_utc->tm_sec ];
    }

      if ( [identifier isEqualToString:[[NSNumber numberWithInt:(i+1)]
    stringValue]])
      {
      return [NSNumber numberWithDouble:k2700_str[Row].channel[i]];
      }
    }

    }

    Any ideas ?

    Thanks

    Gilles Celli

    On Oct 13, 2006, at 6:15 PM, R. Matthew Emerson wrote:

    >
    > On Oct 13, 2006, at 11:43 AM, Gilles Celli wrote:
    >
    >>
    >> On Oct 13, 2006, at 5:39 PM, Glenn Zelniker wrote:
    >>
    >>>
    >>> On Oct 13, 2006, at 11:34 AM, Gilles Celli wrote:
    >>>
    >>>>> I'm assuming that you're trying to display in your table the
    >>>>> data for a number of sensors (indicated by a column) at
    >>>>> different points in time (indicated by row position). Is this
    >>>>> correct?
    >>>> yes right! In fact voltage values for a 16 channel multimeter.
    >>>> The NSTableView columns have numerical identifiers (1-16) and
    >>>> with Date/Time (but not implemented yet...).
    >>>
    >>> Until you implement the Date/Time and map it to a row index,
    >>> you're not going to see anything meaningful in your table.
    >>>
    >>> GZ
    >>>
    >> so you think I that I should return a NSCalendarDate in method -
    >> (int)numberOfRowsInTableView... ?
    >
    > No, that wouldn't do anything useful.
    >
    > (Warning, code typed in mail.)
    >
    > Say that you place each sample acquired from the digital multimeter
    > into a C struct.  (I seem to recall that you were asking about
    > putting data stored in a C array into a table view, so I'll use
    > vanilla C rather than objects.)
    >
    > #include <sys/time.h>
    >
    > struct sample {
    > struct timeval tv;    /* via gettimeofday(2), for example, or use
    > NSDate */
    > double channels[15];
    > };
    >
    > struct sample samples[20000];    /* or dynamically allocate */
    > int nsamples;
    >
    > Then your table view data source methods might look something like
    > this:
    >
    > - (int) numberOfRowsInTableView:(NSTableView *)tableView
    > {
    > return nsamples;
    > }
    >
    > - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:
    > (NSTableColumn *)Column row:(int)Row
    > {
    > struct sample s = samples[Row];
    >
    > if ([[Column identifier] isEqualToString:@"1"])
    > return [NSNumber numberWithDoublle:s.channels[0]];
    > else if ([[Column identifier] isEqualToString:@"2"])
    > return [NSNumber numberWithDoublle:s.channels[1]];
    > etc.
    >
    > }
    >
    > You could also put the timestamps in the table view by adding
    > another column with an identifier of "timestamp", and formatting
    > the struct timeval appropriately.
    >
    >
    >
  • Sorry guys, I've found the error: since I'm using a pointer of
    'struct tm *tm_utc' it will not work.

    I've fixing it by simply copying the tm_utc structure in their resp.
    variables, like:
    second = tm_utc->tm_sec;

    or I will use a NSCalendarDate....

    On Oct 25, 2006, at 4:24 PM, Gilles Celli wrote:

    > Hello,
    >
    > Hope someone remembers my problem I had with NSTableView....
    > I've been quite busy these last days coding and I got finally a
    > working NSTableView with acquired data from a Keithley Multimeter
    > with 16 channels (via USB port).
    >
    > For speed and memory efficiency I'm just using plain old C-
    > structure instead of NSArray as you guys suggested here on the
    > mailing-list.
    > This works great!!
    >
    > However I have the following problem:
    >
    > The timevalue of the acquisiton in the NSTableview gets updated but
    > every row gets the same value... the channel values are correct.
    >
    > Remember that the acquisition is every 5seconds....making an NSLog
    > of the time structure correctly spits out the time.
    >
    > E.g in NSTableView:
    >
    > Time        |  Chan1  | Chan 2 | ...
    > 14:51:05    |  0.912     |  0.122    |
    > 14:51:05    |  1.331    |  0.811    | <= time bug, should be +5 seconds :-(
    > 14:51:05    |  1.331    |  0.811    | <= time bug, should be +10 seconds :-(
    >
    >
    > Here's my C-structure declared in my class:
    >
    > struct keithley_struct {
    >
    > // Normal time structure
    > struct tm *tm_utc;
    >
    > double channel[MAX_NBR_OF_CHANNELS];
    >
    > } k2700_data[MAX_ACQ_DATA_PER_DAY];
    >
    > And here from my Controller the tableView code:
    >
    > - (int) numberOfRowsInTableView:(NSTableView *)tableView
    > {
    > return [k2700 currentRow];
    > }
    >
    >
    > - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:
    > (NSTableColumn *)Column row:(int)Row
    > {
    > int i=0;
    > NSString *identifier = [Column identifier];
    >
    > struct keithley_struct *k2700_str;
    >
    > k2700_str = [k2700 k2700_data];
    >
    >
    > for (i=0 ; i <= NBR_OF_CHANNELS; i++)
    > {
    > if ( [identifier isEqualToString:@"time"])
    > {
    > return [NSNumber numberWithInt:k2700_str[Row].tm_utc->tm_sec ];
    > }
    >
    > if ( [identifier isEqualToString:[[NSNumber numberWithInt:(i+1)]
    > stringValue]])
    > {
    > return [NSNumber numberWithDouble:k2700_str[Row].channel[i]];
    > }
    > }
    >
    > }
    >
    >
    > Any ideas ?
    >
    > Thanks
    >
    > Gilles Celli
    >
    >
    >
    >
    >
    > On Oct 13, 2006, at 6:15 PM, R. Matthew Emerson wrote:
    >
    >>
    >> On Oct 13, 2006, at 11:43 AM, Gilles Celli wrote:
    >>
    >>>
    >>> On Oct 13, 2006, at 5:39 PM, Glenn Zelniker wrote:
    >>>
    >>>>
    >>>> On Oct 13, 2006, at 11:34 AM, Gilles Celli wrote:
    >>>>
    >>>>>> I'm assuming that you're trying to display in your table the
    >>>>>> data for a number of sensors (indicated by a column) at
    >>>>>> different points in time (indicated by row position). Is this
    >>>>>> correct?
    >>>>> yes right! In fact voltage values for a 16 channel multimeter.
    >>>>> The NSTableView columns have numerical identifiers (1-16) and
    >>>>> with Date/Time (but not implemented yet...).
    >>>>
    >>>> Until you implement the Date/Time and map it to a row index,
    >>>> you're not going to see anything meaningful in your table.
    >>>>
    >>>> GZ
    >>>>
    >>> so you think I that I should return a NSCalendarDate in method -
    >>> (int)numberOfRowsInTableView... ?
    >>
    >> No, that wouldn't do anything useful.
    >>
    >> (Warning, code typed in mail.)
    >>
    >> Say that you place each sample acquired from the digital
    >> multimeter into a C struct.  (I seem to recall that you were
    >> asking about putting data stored in a C array into a table view,
    >> so I'll use vanilla C rather than objects.)
    >>
    >> #include <sys/time.h>
    >>
    >> struct sample {
    >> struct timeval tv;    /* via gettimeofday(2), for example, or use
    >> NSDate */
    >> double channels[15];
    >> };
    >>
    >> struct sample samples[20000];    /* or dynamically allocate */
    >> int nsamples;
    >>
    >> Then your table view data source methods might look something like
    >> this:
    >>
    >> - (int) numberOfRowsInTableView:(NSTableView *)tableView
    >> {
    >> return nsamples;
    >> }
    >>
    >> - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:
    >> (NSTableColumn *)Column row:(int)Row
    >> {
    >> struct sample s = samples[Row];
    >>
    >> if ([[Column identifier] isEqualToString:@"1"])
    >> return [NSNumber numberWithDoublle:s.channels[0]];
    >> else if ([[Column identifier] isEqualToString:@"2"])
    >> return [NSNumber numberWithDoublle:s.channels[1]];
    >> etc.
    >>
    >> }
    >>
    >> You could also put the timestamps in the table view by adding
    >> another column with an identifier of "timestamp", and formatting
    >> the struct timeval appropriately.
    >>
    >>
    >>
    >
previous month october 2006 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today