tableView Issues with data and xml

Ok, I am not sure if this is a bug or something  in my coding I am doing totally wrong, but after 3 days on this issue in my app I am at wits end.  :angry:  It is probably something I am overlooking, but I am not sure so here goes…

The issue at hand is when I run the scene, everything loads perfectly fine. However, when i scroll through the tableView that is created, when it reaches the bottom entry, that entry duplicates for the amount of total entries, then when I scroll back up it is the only entry filling the entire table. Also, for some reason my separator line only appears every 2 entries in the simulator. The line however does work fine on the device. Screen Shots are attached - SS1 is the initial loading of the scene - everything is as it should be.  SS2 is where the list should end - the MAR 15th entry is the last entry in the XML File. SS3 is after you scroll to the bottom of the tableView, for some reason it has taken the last entry and multiplied it by the number of rows and inserted it. SS4 is after scrolling back to the top of the tableView, and now all my rows have been replaced with that last row of data. another thing to note when i click on the row and it moves to the view page, from SS1 it pulls the data from the row and displays it, from SS4 it now pulls the data from that last row, which is how i figured out it was actually replacing the row with the last data entry in the table generated from the XML file. 

Here is the code for the scene I am having issues with…

[lua]

local widget = require( “widget” )

local storyboard = require( “storyboard” )

local scene = storyboard.newScene()


– 

–      NOTE:

–      

–      Code outside of listener functions (below) will only be executed once,

–      unless storyboard.removeScene() is called.

– 


listFlag = true;

– local forward references should go here –

– create a constant for the left spacing of the row content

 function makeTimeStamp(dateString)

  --local pattern = “(%d+)%-(%d+)%-(%d+)%a(%d+)% :(%d+)% :([%d%.])”

  local pattern = “(%d+)%-(%d+)%-(%d+)%a(%d+)% :(%d+)% :([%d%.])”

  eYear, eMonth, eDay, eHour, eMinute, eSeconds = dateString:match(pattern)  

end

function setMonth()

  if eMonth == “01” then 

    eMonth = “JAN”

  elseif

    eMonth == “02” then

    eMonth = “FEB”

  elseif

    eMonth == “03” then

    eMonth = “MAR”

  elseif

    eMonth == “04” then

    eMonth = “APR”

  elseif

    eMonth == “05” then

    eMonth = “MAY”

  elseif

    eMonth == “06” then

    eMonth = “JUN”

  elseif

    eMonth == “07” then

    eMonth = “JUL”

  elseif

    eMonth == “08” then

    eMonth = “AUG”

  elseif

    eMonth == “09” then

    eMonth = “SEP”

  elseif

    eMonth == “10” then

    eMonth = “OCT”

  elseif

    eMonth == “11” then

    eMonth = “NOV”

  elseif

    eMonth == “12” then

    eMonth = “DEC”

  end

  

  end


– BEGINNING OF YOUR IMPLEMENTATION


function goBackHome()

   

   storyboard.gotoScene( “iphone4.homescreen” )

 end

– Called when the scene’s view does not exist:

function scene:createScene( event )

        local group = self.view

local bgGroup = display.newGroup()

local tableGroup = display.newGroup()

        -----------------------------------------------------------------------------

        –      CREATE display objects and add them to ‘group’ here.

        –      Example use-case: Restore ‘group’ from previously saved state.

        -----------------------------------------------------------------------------

local tableView = nil

     – insert backgrounds, set up 0 scale and alpha for transition 

          mainBG = display.newImageRect(“images/bgAll_i4.png”, _W, _H);

          mainBG.x = halfW; mainBG.y = halfH;

          bgGroup:insert(mainBG)

          – Create toolbar to go at the top of the screen

          – Create a title bar

          – The gradient used by the title bar

          local titleGradient = {

              type = ‘gradient’,

              color1 = { 0/255, 0/255, 0/255, 255/255 }, 

              color2 = { 35/255,35/255, 35/255, 255/255 },

              direction = “down”

            }

          – Create toolbar to go at the top of the screen

          local titleBar = display.newRect( halfW, 0, _W-10, 66 );

          titleBar:setFillColor( titleGradient ); 

          titleBar.y = titleBar.contentHeight * 0.5 +3;

          local titleText = display.newText( “Royal Bliss On Tour”, halfW, titleBar.y+3, “ChunkFive-Roman”, 30 );

          local hrTop = display.newLine( 0,69, _W-2, 69 );

          hrTop:setStrokeColor( 255, 255, 255, 255 );

          hrTop.strokeWidth = .75;

          local iconBack = display.newImageRect(“images/btnBack.png”, 90, 60);

          iconBack.x=70; iconBack.y = titleBar.y+2;

          

    – Text to show which item we selected

    

 local textRoyalBliss = display.newText( “Royal Bliss”, 0, 0, “ChunkFive-Roman”, 28 )

  textRoyalBliss.x = display.contentWidth + textRoyalBliss.contentWidth

    textRoyalBliss.y = 60 --display.contentCenterY - itemSelected.contentHeight

    tableGroup:insert( textRoyalBliss )

  

  local textVenueLoc = display.newText( “”, 0, 0, “ArialRoundedMTBold”, 12 )

  textVenueLoc.x = display.contentWidth + textVenueLoc.contentWidth

    textVenueLoc.y = 80 --display.contentCenterY - itemSelected.contentHeight

    tableGroup:insert( textVenueLoc )

  

  --local myVenueMap = native.newMapView( 20, 100, 290, 220 )

  --myVenueMap.mapType = “standard”

  --myVenueMap:addMarker( 100, -100 )

  --tableGroup:insert( myVenueMap )

    – Function to return to the list

    local function goBack( event )

    – see if date or home

    if listFlag == true then

      storyboard.gotoScene( “iPhone4.homescreen” )

      else

    titleText.text = “Royal Bliss On Tour” 

    

        --Transition in the list, transition out the item selected text and the back button

        – The table x origin refers to the center of the table in Graphics 2.0, so we translate with half the object’s contentWidth

        transition.to( tableView, { x = tableView.contentWidth * 0.5 +5, time = 400, transition = easing.outExpo } )

        

    transition.to( textRoyalBliss, { x = display.contentWidth + textRoyalBliss.contentWidth, time = 400, transition = easing.outExpo } )

    transition.to( textVenueLoc, { x = display.contentWidth + textVenueLoc.contentWidth, time = 400, transition = easing.outExpo } )

        --transition.to( event.target, { x = display.contentWidth + event.target.contentWidth, time = 400, transition = easing.outQuad } )

    

    --iconBack:removeEventListener(“touch”, goBack )

end

timer.performWithDelay(800, function() listFlag = true end, 1);

    end

    

  iconBack:addEventListener(“touch”, goBack )

  

  

    – Listen for tableView events

    local function tableViewListener( event )

        local phase = event.phase

        

        print( “Event.phase is:”, event.phase )

    end

    – Handle row rendering

    local function onRowRender( event )  

        local phase = event.phase

        local row = event.row

        row.index = eventID; row.venueCity = eventCity; row.month = eMonth; row.day = eDay; row.year = eYear; row.venueName = eventVenue; 

    local groupContentHeight = row.contentHeight  

    local rowIcon = display.newImageRect(row, “images/calendar_icon.png”, 105, 105); rowIcon.x = 31;

    local rowVenue = display.newText( row, eventVenue, 140, 0, “ArialRoundedMTBold”, 30 );

    local rowCity = display.newText( row, eventCity, 140, 0, “ArialRoundedMTBold”, 24 );

    local rowMonth = display.newText( row, eMonth, 65, 0, “ArialRoundedMTBold”, 20 );

    local rowDay = display.newText( row, eDay, 53, 0, “Arial-Black”, 46 );

        rowCity.anchorX = 0; rowVenue.anchorX = 0; rowIcon.anchorX = 0; rowMonth.anchorX = 0; rowDay.anchorX = 0;

        rowCity.y = groupContentHeight * 0.63; rowCity:setFillColor( 255, 255, 255 );

    rowVenue.y = groupContentHeight * 0.35; rowVenue:setFillColor( 255, 255, 255 );

    rowMonth.y = groupContentHeight * 0.28; rowMonth:setFillColor( 255, 255, 255 );

    rowDay.y = groupContentHeight * 0.60; rowDay:setFillColor( 0, 0, 0 );

    rowIcon.y = groupContentHeight * 0.5; 

    end

    

    – Handle row updates

    local function onRowUpdate( event )

        local phase = event.phase

        local row = event.row

        

        print( row.index, “: is now onscreen” )

    end

    

    – Handle touches on the row

    local function onRowTouch( event )

        local phase = event.phase

        local row = event.target

                

        if “release” == phase then

            --Update the item selected text

        

      titleText.text = row.month … " " … row.day … ", " …row.year

      textVenueLoc.text = "At:  " …row.venueName

            dataID = row.index

      listFlag = false;

            --Transition out the list, transition in the item selected text and the back button

            – The table x origin refers to the center of the table in Graphics 2.0, so we translate with half the object’s contentWidth

            transition.to( tableView, { x = - tableView.contentWidth, time = 400, transition = easing.outExpo } )

            transition.to( myVenueMap, { x = display.contentCenterX, time = 400, transition = easing.outExpo } )

      transition.to( textRoyalBliss, { x = display.contentCenterX, time = 400, transition = easing.outExpo } )

      transition.to( textVenueLoc, { x = display.contentCenterX, time = 400, transition = easing.outExpo } )

            --transition.to( backButton, { x = display.contentCenterX, time = 400, transition = easing.outQuad } )

        end

    end

  

  local function networkListener( event )

        if ( event.isError ) then

                print( “Network error - download failed” )

        elseif ( event.phase == “began” ) then

                print( “Progress Phase: began” )

                native.setActivityIndicator(true)

        elseif ( event.phase == “ended” ) then

                print( “loading XML data for Parsing” )

                native.setActivityIndicator(false)

              end

              

            end

            

  local params = {}

        params.progress = true

network.download(

        --“http://www.coronalabs.com/images/downloadnow.png”,

        --“http://api.bandsintown.com/artists/Royal%20Bliss/events.xml?api_version=2.0&app_id=rbMobileApp”,

        “http://api.bandsintown.com/artists/buckcherry/events.xml?api_version=2.0&app_id=rbMobileApp”,

        “GET”,

        networkListener,

        params,

        “tourdates.xml”,

        --“helloCopy.png”,

        system.TemporaryDirectory

        )

  

 function createData()

   local xml = require( “xml” ).newParser()

   local events = xml:loadFile( “tourdates.xml”, system.TemporaryDirectory )

   

    onTour = {}

                – for each “child” in the table…

                for i=1,#events.child do

                – store the event info table

        event[i] = events.child[i]

                end

            print(“Total rows:” … table.getn( event ) )           

            

   

 – Create 100 rows

    for i = 1,#event do

    eventID = event[i].child[1].value

    

          eventVenue = event[i].child[14].child[1].value

      print(eventVenue)

      if string.len(eventVenue) > 28 then

        eventVenue = string.sub(eventVenue, 1, 28) … “…”

    end

      eventCity = event[i].child[5].value

      print(eventCity)

      if string.len(eventCity) > 28 then

        eventCity = string.sub(eventCity, 1, 28) … “…”

    end

    eventDateCode = event[i].child[3].value

            print (eventDateCode)

    makeTimeStamp(eventDateCode)

            print (eDay)

            setMonth(eMonth)

            print (eMonth)

            print(eYear)

        local rowHeight = 118;

        local rowColor = 

        { 

            default = { 255, 255, 255, 0 },

            over = { 30/255, 144/255, 1 },

        }

        local lineColor = { 255/255, 255/255, 255/255 }

        

    

        

        – Insert the row into the tableView

        tableView:insertRow

        {

            

            rowHeight = rowHeight,

            rowColor = rowColor,

            lineColor = lineColor,

        }

    end

  end --createData

    

    – Create a tableView

    tableView = widget.newTableView

    {

        top = 75,

    left = 10,

        width = 620, 

        height = 875,

        listener = tableViewListener,

        onRowRender = onRowRender,

        onRowUpdate = onRowUpdate,

        onRowTouch = onRowTouch,

    hideBackground = true,

    --noLines = true,

    }

  createData()

    tableGroup:insert( tableView )

    

    

end

– Called BEFORE scene has moved onscreen:

function scene:willEnterScene( event )

        local group = self.view

        -----------------------------------------------------------------------------

        –      This event requires build 2012.782 or later.

        -----------------------------------------------------------------------------

end

– Called immediately after scene has moved onscreen:

function scene:enterScene( event )

        local group = self.view

        -----------------------------------------------------------------------------

        –      INSERT code here (e.g. start timers, load audio, start listeners, etc.)

        -----------------------------------------------------------------------------

end

– Called when scene is about to move offscreen:

function scene:exitScene( event )

        local group = self.view

        -----------------------------------------------------------------------------

        –      INSERT code here (e.g. stop timers, remove listeners, unload sounds, etc.)

        -----------------------------------------------------------------------------

end

– Called AFTER scene has finished moving offscreen:

function scene:didExitScene( event )

        local group = self.view

        -----------------------------------------------------------------------------

        –      This event requires build 2012.782 or later.

        -----------------------------------------------------------------------------

end

– Called prior to the removal of scene’s “view” (display group)

function scene:destroyScene( event )

        local group = self.view

        -----------------------------------------------------------------------------

        –      INSERT code here (e.g. remove listeners, widgets, save state, etc.)

        -----------------------------------------------------------------------------

end

– Called if/when overlay scene is displayed via storyboard.showOverlay()

function scene:overlayBegan( event )

        local group = self.view

        local overlay_name = event.sceneName  – name of the overlay scene

        -----------------------------------------------------------------------------

        –      This event requires build 2012.797 or later.

        -----------------------------------------------------------------------------

end

– Called if/when overlay scene is hidden/removed via storyboard.hideOverlay()

function scene:overlayEnded( event )

        local group = self.view

        local overlay_name = event.sceneName  – name of the overlay scene

        -----------------------------------------------------------------------------

        –      This event requires build 2012.797 or later.

        -----------------------------------------------------------------------------

end


– END OF YOUR IMPLEMENTATION


– “createScene” event is dispatched if scene’s view does not exist

scene:addEventListener( “createScene”, scene )

– “willEnterScene” event is dispatched before scene transition begins

scene:addEventListener( “willEnterScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished

scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched before next scene’s transition begins

scene:addEventListener( “exitScene”, scene )

– “didExitScene” event is dispatched after scene has finished transitioning out

scene:addEventListener( “didExitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be

– automatically unloaded in low memory situations, or explicitly via a call to

– storyboard.purgeScene() or storyboard.removeScene().

scene:addEventListener( “destroyScene”, scene )

– “overlayBegan” event is dispatched when an overlay scene is shown

scene:addEventListener( “overlayBegan”, scene )

– “overlayEnded” event is dispatched when an overlay scene is hidden/removed

scene:addEventListener( “overlayEnded”, scene )


return scene

[/lua]

Yes, I know I have some other things to clean up in this, but right now this data feed issue is my main problem. Also, hopefully once this is all done and working I’ll be able to separate out this whole function and create a plugin  - What this does is takes an XML download from bandsintown and load tour dates into the tableview - then when you click on the date it will open a page with venue and ticket info as well as a map and other event info from the data pulled. I don’t know if any of you out there are working on any business type apps and might find this useful or not :slight_smile:

Thanks in advance for any help or pointing in the right direction with this :slight_smile:

Let me address the lines problem first.  This is most likely due to your skin being zoomed out.  It looks like you’re using the iPhone 5 skin, which has a viewable area of 1136 pixels high.  By the time the skin gets added around the viewport, your total window size is probably bigger than your monitor.  In my case, I’m on a 1920 x 1080 screen…  The 1136px high viewport is already taller than my screen, so I typically zoom in to get the whole skin on screen.  When you reduce the screen by half, then half the pixel rows get thrown away, ergo your line only shows up every couple of rows.  If you zoom in (CMD-+) you should see all of them.

Now for the more pressing problem is how you are inserting your data into your table.  The tableView uses asynchronous events to draw each cell.  When a row scrolls off screen, it’s destroyed and when it comes back on screen, it’s rendered.  Because your variables like eventVenue and eventCity are holding the last value that was processed in your initial for loop, when the row gets rendered again, it’s picking up those values.

The traditional way of solving this is to have a table of data that matches each row in the tableView.  So you could have:

eventData = {}

for i = 1, #event do

      –

      – your code to figure out eventVenue, eventCity etc.

      –

      eventData[i] = {}

      eventData[i].venue eventVenue

      eventData[i].city = eventCity

      –

      – your code to insert the rows

      –

end

Then in your onRowRender() function you use the row.index to get the actual data.  You are overwriting row.index which you probably should not do.  Then you can build your display like:

local rowVenue = display.newText( row, eventData[event.index].venue, 140, 0, “ArialRoundedMTBold”, 30 );

Rob

Rob,

Thank you so much! I didn’t realize about the zooming, i’ll keep that in mind for the future as i too am running 1080P monitors.

As far as the rest - you sir are pure genius :slight_smile: the secondary table worked perfectly, and I did change the row.index so as not to assign it and just created another ID  (index) field to hold the actual record ID which is used on the detail page to pull the rest of the data from the particular data record. 

Again Rob, Thanks! Actually a double thanks for replying on a Sunday! :slight_smile: Corona has some of the BEST forum support I have ever seen!

One caveat, if you ever choose to use category rows, they count as rows too and your data table index’s won’t line up with the tableView’s indexes and there are other things you have to do to work around that.  But it didn’t look like you are going to use category rows.

Rob

Let me address the lines problem first.  This is most likely due to your skin being zoomed out.  It looks like you’re using the iPhone 5 skin, which has a viewable area of 1136 pixels high.  By the time the skin gets added around the viewport, your total window size is probably bigger than your monitor.  In my case, I’m on a 1920 x 1080 screen…  The 1136px high viewport is already taller than my screen, so I typically zoom in to get the whole skin on screen.  When you reduce the screen by half, then half the pixel rows get thrown away, ergo your line only shows up every couple of rows.  If you zoom in (CMD-+) you should see all of them.

Now for the more pressing problem is how you are inserting your data into your table.  The tableView uses asynchronous events to draw each cell.  When a row scrolls off screen, it’s destroyed and when it comes back on screen, it’s rendered.  Because your variables like eventVenue and eventCity are holding the last value that was processed in your initial for loop, when the row gets rendered again, it’s picking up those values.

The traditional way of solving this is to have a table of data that matches each row in the tableView.  So you could have:

eventData = {}

for i = 1, #event do

      –

      – your code to figure out eventVenue, eventCity etc.

      –

      eventData[i] = {}

      eventData[i].venue eventVenue

      eventData[i].city = eventCity

      –

      – your code to insert the rows

      –

end

Then in your onRowRender() function you use the row.index to get the actual data.  You are overwriting row.index which you probably should not do.  Then you can build your display like:

local rowVenue = display.newText( row, eventData[event.index].venue, 140, 0, “ArialRoundedMTBold”, 30 );

Rob

Rob,

Thank you so much! I didn’t realize about the zooming, i’ll keep that in mind for the future as i too am running 1080P monitors.

As far as the rest - you sir are pure genius :slight_smile: the secondary table worked perfectly, and I did change the row.index so as not to assign it and just created another ID  (index) field to hold the actual record ID which is used on the detail page to pull the rest of the data from the particular data record. 

Again Rob, Thanks! Actually a double thanks for replying on a Sunday! :slight_smile: Corona has some of the BEST forum support I have ever seen!

One caveat, if you ever choose to use category rows, they count as rows too and your data table index’s won’t line up with the tableView’s indexes and there are other things you have to do to work around that.  But it didn’t look like you are going to use category rows.

Rob