Scene continues to run when hidden

I have a scene that makes a network request but requires a date to be entered before making the request.

I use a different scene to call the datePickerWheel (https://code.coronalabs.com/code/date-picker-wheel-widget). My new scene is based on the example.lua code provided with this widget.

The problem is that when I call the function to getDate, that in turn goes to scDatePicker scene, the code in the parent scene continues to run - in this case the network request is made.

parent scene ... local deDate = getDate() local depDate = "/departing/" .. deDate local FLT\_Qry = "https://api.flightstats.com/flex/schedules/rest/v1/json/flight/" .. FltRef .. depDate .. G.\_FSAPIid .. "&codeType=FS" print ("Flight Query: " .. FLT\_Qry) network.request( FLT\_Qry, "GET", handleAPISxResponse ) .... \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ local function getDate()      --print ("In Get Date ... ")     --local \_Date = os.date("\*t")         --local retDate = \_Date.year .. "/" .. \_Date.month .. "/" .. (\_Date.day) --print(retDate)     composer.gotoScene("scDatePicker")          local retDate = G.\_userDate.year .. "/" .. G.\_userDate.month .. "/" .. G.\_userDate.day          return retDate      end

Any suggestions??

You should control the line :

[lua]  

      network.request( FLT_Qry, “GET”, handleAPISxResponse )  

[/lua]

Keep the validations on input field that you take from user , & then onSubmit hit the network.request()

Note : Kindly submit clean block of code next time, its very confusing for anyone here to detect.

-Assif

Hi Assif, thanks for your response and I note your comment re clean code. Clean code provide below.

parent scene local deDate = getDate() local depDate = "/departing/" .. deDate local FLT\_Qry = "https://api.flightstats.com/flex/schedules/rest/v1/json/flight/" .. FltRef .. depDate .. G.\_FSAPIid .. "&codeType=FS" network.request( FLT\_Qry, "GET", handleAPISxResponse ) \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ local function getDate() composer.gotoScene("scDatePicker") local retDate = G.\_userDate.year .. "/" .. G.\_userDate.month .. "/" .. G.\_userDate.day return retDate end

I think I have narrowed the problem down to the way the Date Picker Scene is managing things. I have included the code below. It seems that the scene reaches the show.will phase but then returns to running code from parent scene and in parallel  continues to progress the Date Picker scene through to scene:show.did.

In the attached screenshot the Alert Message that is seen at the bottom of the shot is called by the parent scene when the network.request fails in its search. This means that the code in the parent scene is running - but the Date Picker scene is on the screen.

-- Date Picker example local composer = require("composer") local G = require("data") local scene = composer.newScene() local widget = require("widget") require("datePickerWheel") --------------------------------------------------------------------------------- -- All code outside of the listener functions will only be executed ONCE -- unless "composer.removeScene()" is called. --------------------------------------------------------------------------------- -- local forward references should go here local loaded -- Add widgets to this table so they get removed automatically. local widgets = {} local displayText, datePicker local function validateDate(m, d, y) --[[If you want to validate that the user chose a date in the past. Parameters: m : int | string Month number (not name!) d : int | string Day y : int | string Year]] local time = os.time({year=y, month=m, day=d}) if time \> os.time() then native.showAlert("Date Picker", "You cannot choose a date in the future.", {"OK"}) return false end return true end local function closeScene() composer.gotoScene("scOpen") end local function onAccept() -- Make sure the scene is fully loaded before we accept button events. if not loaded then return true end local values = datePicker:getValues() -- CORONA BUG: Sometimes the values can be nil. -- This happens when one of the tables stopped scrolling but hasn't "snapped" to a selected index. -- Prompt the user to fix the bad column. if not values[1] then native.showAlert("Flight Log", "Please make sure a month is selected.", {"OK"}) elseif not values[2] then native.showAlert("Flight Log", "Please make sure a day is selected.", {"OK"}) elseif not values[3] then native.showAlert("Flight Log", "Please make sure a year is selected.", {"OK"}) else local valid = validateDate(values[1].index, values[2].value, values[3].value) if valid then displayText.text = values[1].value .. " " .. values[2].value .. ", " .. values[3].value G.\_userDate = { month = values[1].value, day = values[2].value, year = values[3].value } end end return true -- indicates successful touch end --------------------------------------------------------------------------------- -- "scene:create()" function scene:create(event) local sceneGroup = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. local okBtn = widget.newButton{ label="Accept" } widgets[#widgets+1] = okBtn okBtn.anchorY = 0 okBtn.x = display.contentCenterX okBtn.y = G.\_mbHgt + 10 okBtn:addEventListener( "touch", onAccept ) local closeBtn = widget.newButton{ label="Close" } widgets[#widgets+1] = closeBtn closeBtn.anchorY = 0 closeBtn.x = display.contentCenterX closeBtn.y = okBtn.y + 30 closeBtn:addEventListener( "touch", closeScene ) -- Figure out which date to start with. local p = event.params or {} local currYear = tonumber(p.year or os.date("%Y")) local currMonth = tonumber(p.month or os.date("%m")) local currDay = tonumber(p.day or os.date("%d")) -- Create the widget. datePicker = widget.newDatePickerWheel(currYear, currMonth, currDay) widgets[#widgets+1] = datePicker -- Position it however you like. datePicker.anchorChildren = true datePicker.anchorX = 0.5 datePicker.anchorY = 0 datePicker.x = okBtn.x datePicker.y = closeBtn.y + closeBtn.height + 10 -- Display the selected date when user presses "Accept" displayText = display.newText{ text = "The Date Picker supports months with different days, and even leap years!", width = display.contentWidth - 20, font = native.systemFont, fontSize = 18, align = "center" } displayText:setFillColor(1) displayText.anchorY = 0 displayText.x = datePicker.x displayText.y = datePicker.y + datePicker.height + 10 sceneGroup:insert(okBtn) sceneGroup:insert(closeBtn) sceneGroup:insert(datePicker) sceneGroup:insert(displayText) end -- "scene:show()" function scene:show(event) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is still off screen (but is about to come on screen). elseif phase == "did" then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc. loaded = true end end -- "scene:hide()" function scene:hide(event) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is on screen (but is about to go off screen). -- Insert code here to "pause" the scene. -- Example: stop timers, stop animation, stop audio, etc. loaded = false elseif phase == "did" then -- Called immediately after scene goes off screen. end end -- "scene:destroy()" function scene:destroy(event) local sceneGroup = self.view -- Called prior to the removal of scene's view ("sceneGroup"). -- Insert code here to clean up the scene. -- Example: remove display objects, save state, etc. for i=1, #widgets do local w = table.remove(widgets) if w then w:removeSelf() w = nil end end widgets = nil end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener("create", scene) scene:addEventListener("show", scene) scene:addEventListener("hide", scene) scene:addEventListener("destroy", scene) --------------------------------------------------------------------------------- return scene

Thinking more about Assif’s comment I restructured the code to better control the program flow. I was trying to do too much with the Search Button - get the date, then run the search. I separated the 2 activities so there is a deliberate get date call, then the user runs the search. this solved the problem.

Hey,that’s great if you resolved it.

keep it up joncbo1  :slight_smile:

You should control the line :

[lua]  

      network.request( FLT_Qry, “GET”, handleAPISxResponse )  

[/lua]

Keep the validations on input field that you take from user , & then onSubmit hit the network.request()

Note : Kindly submit clean block of code next time, its very confusing for anyone here to detect.

-Assif

Hi Assif, thanks for your response and I note your comment re clean code. Clean code provide below.

parent scene local deDate = getDate() local depDate = "/departing/" .. deDate local FLT\_Qry = "https://api.flightstats.com/flex/schedules/rest/v1/json/flight/" .. FltRef .. depDate .. G.\_FSAPIid .. "&codeType=FS" network.request( FLT\_Qry, "GET", handleAPISxResponse ) \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ local function getDate() composer.gotoScene("scDatePicker") local retDate = G.\_userDate.year .. "/" .. G.\_userDate.month .. "/" .. G.\_userDate.day return retDate end

I think I have narrowed the problem down to the way the Date Picker Scene is managing things. I have included the code below. It seems that the scene reaches the show.will phase but then returns to running code from parent scene and in parallel  continues to progress the Date Picker scene through to scene:show.did.

In the attached screenshot the Alert Message that is seen at the bottom of the shot is called by the parent scene when the network.request fails in its search. This means that the code in the parent scene is running - but the Date Picker scene is on the screen.

-- Date Picker example local composer = require("composer") local G = require("data") local scene = composer.newScene() local widget = require("widget") require("datePickerWheel") --------------------------------------------------------------------------------- -- All code outside of the listener functions will only be executed ONCE -- unless "composer.removeScene()" is called. --------------------------------------------------------------------------------- -- local forward references should go here local loaded -- Add widgets to this table so they get removed automatically. local widgets = {} local displayText, datePicker local function validateDate(m, d, y) --[[If you want to validate that the user chose a date in the past. Parameters: m : int | string Month number (not name!) d : int | string Day y : int | string Year]] local time = os.time({year=y, month=m, day=d}) if time \> os.time() then native.showAlert("Date Picker", "You cannot choose a date in the future.", {"OK"}) return false end return true end local function closeScene() composer.gotoScene("scOpen") end local function onAccept() -- Make sure the scene is fully loaded before we accept button events. if not loaded then return true end local values = datePicker:getValues() -- CORONA BUG: Sometimes the values can be nil. -- This happens when one of the tables stopped scrolling but hasn't "snapped" to a selected index. -- Prompt the user to fix the bad column. if not values[1] then native.showAlert("Flight Log", "Please make sure a month is selected.", {"OK"}) elseif not values[2] then native.showAlert("Flight Log", "Please make sure a day is selected.", {"OK"}) elseif not values[3] then native.showAlert("Flight Log", "Please make sure a year is selected.", {"OK"}) else local valid = validateDate(values[1].index, values[2].value, values[3].value) if valid then displayText.text = values[1].value .. " " .. values[2].value .. ", " .. values[3].value G.\_userDate = { month = values[1].value, day = values[2].value, year = values[3].value } end end return true -- indicates successful touch end --------------------------------------------------------------------------------- -- "scene:create()" function scene:create(event) local sceneGroup = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. local okBtn = widget.newButton{ label="Accept" } widgets[#widgets+1] = okBtn okBtn.anchorY = 0 okBtn.x = display.contentCenterX okBtn.y = G.\_mbHgt + 10 okBtn:addEventListener( "touch", onAccept ) local closeBtn = widget.newButton{ label="Close" } widgets[#widgets+1] = closeBtn closeBtn.anchorY = 0 closeBtn.x = display.contentCenterX closeBtn.y = okBtn.y + 30 closeBtn:addEventListener( "touch", closeScene ) -- Figure out which date to start with. local p = event.params or {} local currYear = tonumber(p.year or os.date("%Y")) local currMonth = tonumber(p.month or os.date("%m")) local currDay = tonumber(p.day or os.date("%d")) -- Create the widget. datePicker = widget.newDatePickerWheel(currYear, currMonth, currDay) widgets[#widgets+1] = datePicker -- Position it however you like. datePicker.anchorChildren = true datePicker.anchorX = 0.5 datePicker.anchorY = 0 datePicker.x = okBtn.x datePicker.y = closeBtn.y + closeBtn.height + 10 -- Display the selected date when user presses "Accept" displayText = display.newText{ text = "The Date Picker supports months with different days, and even leap years!", width = display.contentWidth - 20, font = native.systemFont, fontSize = 18, align = "center" } displayText:setFillColor(1) displayText.anchorY = 0 displayText.x = datePicker.x displayText.y = datePicker.y + datePicker.height + 10 sceneGroup:insert(okBtn) sceneGroup:insert(closeBtn) sceneGroup:insert(datePicker) sceneGroup:insert(displayText) end -- "scene:show()" function scene:show(event) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is still off screen (but is about to come on screen). elseif phase == "did" then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc. loaded = true end end -- "scene:hide()" function scene:hide(event) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is on screen (but is about to go off screen). -- Insert code here to "pause" the scene. -- Example: stop timers, stop animation, stop audio, etc. loaded = false elseif phase == "did" then -- Called immediately after scene goes off screen. end end -- "scene:destroy()" function scene:destroy(event) local sceneGroup = self.view -- Called prior to the removal of scene's view ("sceneGroup"). -- Insert code here to clean up the scene. -- Example: remove display objects, save state, etc. for i=1, #widgets do local w = table.remove(widgets) if w then w:removeSelf() w = nil end end widgets = nil end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener("create", scene) scene:addEventListener("show", scene) scene:addEventListener("hide", scene) scene:addEventListener("destroy", scene) --------------------------------------------------------------------------------- return scene

Thinking more about Assif’s comment I restructured the code to better control the program flow. I was trying to do too much with the Search Button - get the date, then run the search. I separated the 2 activities so there is a deliberate get date call, then the user runs the search. this solved the problem.

Hey,that’s great if you resolved it.

keep it up joncbo1  :slight_smile: