Native maps, and other native objects removal in exitScene

I am a newbie in Corona. I searched the internet, and also in Corona Labs Forums, for the solution for this problem. But unfortunately all of them is not working for me. I just want to remove a native map from a scene, when the scene exits, and view it again when the scene is created. Thanks in advance.
By the way, here is my code:
(scene3.lua)

local storyboard = require( "storyboard" ) local scene = storyboard.newScene() function scene:createScene( event ) local group = self.view local bg = display.newRect( 0, 0, display.contentWidth, display.contentHeight ) bg:setFillColor( 255 ) ------------------------------------ -- map ------------------------------------ local mapView = native.newMapView( 20, 40, 300, 220 ) if mapView then mapView.mapType = "normal" mapView.x = display.contentWidth / 2 mapView.y = 120 mapView:setCenter( 14.583417 , 121.058494 ) end group:insert( bg ) end function scene:enterScene( event ) local group = self.view end function scene:exitScene( event ) local group = self.view if mapView then mapView:removeSelf() end end function scene:destroyScene( event ) local group = self.view end scene:addEventListener( "createScene", scene ) scene:addEventListener( "enterScene", scene ) scene:addEventListener( "exitScene", scene ) scene:addEventListener( "destroyScene", scene ) return scene

I just posted this answer in the other topic where you had this problem, so here it is again:

At the top of your code, BEFORE your createScene, enterScene etc functions (i.e. directly beneath the local scene = storyboard.newScene() write this:

local myMap

Just that, not “myMap = native.newMapView” or whatever it is.

 

Then in your createScene function, change this:

local mapView = native.newMapView( 20, 40, 300, 220 )

to this:

mapView = native.newMapView( 20, 40, 300, 220 )

This will allocate your mapView to the previously defined variable called myMap, and make it visible to all functions in that lua file.

 

Then put the 

mapView = nil

 part back into your removal code, after the 

mapView:removeSelf()

Also, since you are unsure about how local variables work, I suggest checking out this blog post:

http://www.coronalabs.com/blog/2011/07/19/local-variables-lua/

I don’t know where I went wrong with this. I did all your instructions but its no good. 

Hi 09.SemperFidelis,

First, on minor suggestion - get rid of line 22 in the code shown above. Native objects can not be inserted into a group. Although it will not generate an error it may help confusion and maintenance in the future.

Ok - So correct me if I’m wrong but I don’t see a purgeScene or removeScene anywhere in your code, especially in your enterScene event handler. So how are you handling the clean-up of scenes when you transition between scenes? In my experience the removal or purging of scenes have an affect on the removal and re-creation of your native items. In one of my apps I use a Map, TextInput, and TextBox - each in different scenes. After a lot of experimentation I found that it works best if I remove the previous scene using:

[lua]

local previous_scene_name = storyboard.getPrevious()

if previous_scene_name ~= nil then

    storyboard.removeScene( previous_scene_name )

end

[/lua]

On line 34 you are removing the Map in the exitScene event handler. Although that should successfully remove the Map when you leave the scene it will not be recreated once you return … unless you remove the scene.

Let me know how far you have gotten.

Line 22 in 09.SemperFidelis’s code is not a native object, it is a newRect background object.

Can you post your whole code after you’ve made those changes 09.SemperFidelis? Then I can see why it’s not working, it may be that I haven’t explained something clearly enough.

Sorry 09.SemperFidelis,

​I didn’t read it thoroughly. Yes, bg is the newRect display object.

Ok. I’ll copy and paste your code into a dummy app containing three scenes. Your scene will be the second scene in the dummy app. Then I will post it all back. 

Give me a bit …

Hi 09.SemperFidelis,

So I quickly created a dummy app, inserted your code, inserted some debugging print statements, and added it to Github. Go to the following page and download or clone the app so you can run it for yourself.

https://github.com/doubleblacktech/Corona-SDk-Storyboard-Sample

  1. I placed your code in the second view - view2.lua

  2. The print() statements in the code will help you understand the flow of scene execution, appearance, and removal as you go from one scene to the next.

  3. I placed the following code in the enterScene handler in all three of the views:

[lua]

local previous_scene_name = storyboard.getPrevious()

if previous_scene_name ~= nil then

    storyboard.removeScene( previous_scene_name )

end

[/lua]

  1. So if you run the app you will be presented with the first scene and a tab bar (it’s only there for demonstration purposes). As you navigate to the second screen you will see the following in your terminal (assuming you started your Corona session with the Terminal)

2013-06-14 08:13:14.354 Corona Simulator[21447:707] view2: OUTSIDE

2013-06-14 08:13:14.355 Corona Simulator[21447:707] view2: createScene()

2013-06-14 08:13:14.356 Corona Simulator[21447:707] WARNING: Map views are not supported in the simulator. Please build for device.

2013-06-14 08:13:14.378 Corona Simulator[21447:707] view2: enterScene()

Ignore the third line because we know that the Map view can not be rendered in the Corona Simulator. I had to build for XCode in order to test and make sure it was working correctly (Wack Wack Golf sounds fun!). Notice that first, any code outside the createScene is executed. Second, the code within the createScene in executed. Third, the code in enterScene is executed. By that time the first scene is now off the screen and we can remove it thus saving memory. Now if you go to the third screen you will see in the Terminal:

2013-06-14 08:26:42.225 Corona Simulator[21447:707] view2: exitScene()

2013-06-14 08:26:42.226 Corona Simulator[21447:707] view3: createScene()

2013-06-14 08:26:42.241 Corona Simulator[21447:707] view3: enterScene()

2013-06-14 08:26:42.241 Corona Simulator[21447:707] removeScene(    view2    )

2013-06-14 08:26:42.241 Corona Simulator[21447:707] view2: destroyScene()

The exitScene handler in view2 is called. Then the createScene in view3 is called. Then the enterScene in view3 is called. At this point view2 is now off screen and we can nor remove it from memory. When the removeScene() method is called it triggers the destroyScene handler on view2. At this point the entire scene including the Map is removed from the view and memory.

Ok. Now go back to the second screen and you will see this in the Terminal:

2013-06-14 08:30:13.641 Corona Simulator[21447:707] view3: exitScene()

2013-06-14 08:30:13.642 Corona Simulator[21447:707] view2: OUTSIDE

2013-06-14 08:30:13.643 Corona Simulator[21447:707] view2: createScene()

2013-06-14 08:30:13.643 Corona Simulator[21447:707] WARNING: Map views are not supported in the simulator. Please build for device.

2013-06-14 08:30:13.671 Corona Simulator[21447:707] view2: enterScene()

Now this is important! The exitScene handler in view3 is called. Any code outside the createScene in view2 is executed - again. Then the code within the createScene in view2 in executed - again. This allows for the recreation of the Map and all other display elements. And finally the enterScene handler is triggered. Now here is where things get interesting. If I change the removeScene statement in view3 to purgeScene then I get the following in the Terminal when I navigate from view3 back to view 2:

2013-06-14 08:38:23.161 Corona Simulator[21447:707] view3: exitScene()

2013-06-14 08:38:23.162 Corona Simulator[21447:707] view2: createScene()

2013-06-14 08:38:23.163 Corona Simulator[21447:707] WARNING: Map views are not supported in the simulator. Please build for device.

2013-06-14 08:38:23.170 Corona Simulator[21447:707] view2: enterScene()

Whoa! None of the code OUTSIDE the createScene in view2 is being executed. If you defined any local variables outside the createScene they will still persist and be available inside the createScene handler BUT any local methods defined OUTSIDE the createScene handler WILL NOT be executed again. Something to remember. You may see some extra print statements in the code and the Terminal output that demonstrates this point.

Now what if I manually remove the Map (mapView:removeSelf()) after the transition from view2 to view3 or view1? You must recreate it either just before view2 enters or sometime after because the Map was removed due to the removeScene method.

Take a look at the code. Play around with it. I had trouble understanding Storyboard scenes and native widgets until I spent a day playing around with a simple app such as this.

Now this is what I normally do for apps that do not have a great number of display elements on each of the scenes. Removing and recreating the entire scene in larger apps or graphic intensive can introduce a noticeable delay when transitioning between scenes. This is just one in many ways to handle situations such as this.

How large or intensive will your app be? I hope this helps.

I just posted this answer in the other topic where you had this problem, so here it is again:

At the top of your code, BEFORE your createScene, enterScene etc functions (i.e. directly beneath the local scene = storyboard.newScene() write this:

local myMap

Just that, not “myMap = native.newMapView” or whatever it is.

 

Then in your createScene function, change this:

local mapView = native.newMapView( 20, 40, 300, 220 )

to this:

mapView = native.newMapView( 20, 40, 300, 220 )

This will allocate your mapView to the previously defined variable called myMap, and make it visible to all functions in that lua file.

 

Then put the 

mapView = nil

 part back into your removal code, after the 

mapView:removeSelf()

Also, since you are unsure about how local variables work, I suggest checking out this blog post:

http://www.coronalabs.com/blog/2011/07/19/local-variables-lua/

I don’t know where I went wrong with this. I did all your instructions but its no good. 

Hi 09.SemperFidelis,

First, on minor suggestion - get rid of line 22 in the code shown above. Native objects can not be inserted into a group. Although it will not generate an error it may help confusion and maintenance in the future.

Ok - So correct me if I’m wrong but I don’t see a purgeScene or removeScene anywhere in your code, especially in your enterScene event handler. So how are you handling the clean-up of scenes when you transition between scenes? In my experience the removal or purging of scenes have an affect on the removal and re-creation of your native items. In one of my apps I use a Map, TextInput, and TextBox - each in different scenes. After a lot of experimentation I found that it works best if I remove the previous scene using:

[lua]

local previous_scene_name = storyboard.getPrevious()

if previous_scene_name ~= nil then

    storyboard.removeScene( previous_scene_name )

end

[/lua]

On line 34 you are removing the Map in the exitScene event handler. Although that should successfully remove the Map when you leave the scene it will not be recreated once you return … unless you remove the scene.

Let me know how far you have gotten.

Line 22 in 09.SemperFidelis’s code is not a native object, it is a newRect background object.

Can you post your whole code after you’ve made those changes 09.SemperFidelis? Then I can see why it’s not working, it may be that I haven’t explained something clearly enough.

Sorry 09.SemperFidelis,

​I didn’t read it thoroughly. Yes, bg is the newRect display object.

Ok. I’ll copy and paste your code into a dummy app containing three scenes. Your scene will be the second scene in the dummy app. Then I will post it all back. 

Give me a bit …

Hi 09.SemperFidelis,

So I quickly created a dummy app, inserted your code, inserted some debugging print statements, and added it to Github. Go to the following page and download or clone the app so you can run it for yourself.

https://github.com/doubleblacktech/Corona-SDk-Storyboard-Sample

  1. I placed your code in the second view - view2.lua

  2. The print() statements in the code will help you understand the flow of scene execution, appearance, and removal as you go from one scene to the next.

  3. I placed the following code in the enterScene handler in all three of the views:

[lua]

local previous_scene_name = storyboard.getPrevious()

if previous_scene_name ~= nil then

    storyboard.removeScene( previous_scene_name )

end

[/lua]

  1. So if you run the app you will be presented with the first scene and a tab bar (it’s only there for demonstration purposes). As you navigate to the second screen you will see the following in your terminal (assuming you started your Corona session with the Terminal)

2013-06-14 08:13:14.354 Corona Simulator[21447:707] view2: OUTSIDE

2013-06-14 08:13:14.355 Corona Simulator[21447:707] view2: createScene()

2013-06-14 08:13:14.356 Corona Simulator[21447:707] WARNING: Map views are not supported in the simulator. Please build for device.

2013-06-14 08:13:14.378 Corona Simulator[21447:707] view2: enterScene()

Ignore the third line because we know that the Map view can not be rendered in the Corona Simulator. I had to build for XCode in order to test and make sure it was working correctly (Wack Wack Golf sounds fun!). Notice that first, any code outside the createScene is executed. Second, the code within the createScene in executed. Third, the code in enterScene is executed. By that time the first scene is now off the screen and we can remove it thus saving memory. Now if you go to the third screen you will see in the Terminal:

2013-06-14 08:26:42.225 Corona Simulator[21447:707] view2: exitScene()

2013-06-14 08:26:42.226 Corona Simulator[21447:707] view3: createScene()

2013-06-14 08:26:42.241 Corona Simulator[21447:707] view3: enterScene()

2013-06-14 08:26:42.241 Corona Simulator[21447:707] removeScene(    view2    )

2013-06-14 08:26:42.241 Corona Simulator[21447:707] view2: destroyScene()

The exitScene handler in view2 is called. Then the createScene in view3 is called. Then the enterScene in view3 is called. At this point view2 is now off screen and we can nor remove it from memory. When the removeScene() method is called it triggers the destroyScene handler on view2. At this point the entire scene including the Map is removed from the view and memory.

Ok. Now go back to the second screen and you will see this in the Terminal:

2013-06-14 08:30:13.641 Corona Simulator[21447:707] view3: exitScene()

2013-06-14 08:30:13.642 Corona Simulator[21447:707] view2: OUTSIDE

2013-06-14 08:30:13.643 Corona Simulator[21447:707] view2: createScene()

2013-06-14 08:30:13.643 Corona Simulator[21447:707] WARNING: Map views are not supported in the simulator. Please build for device.

2013-06-14 08:30:13.671 Corona Simulator[21447:707] view2: enterScene()

Now this is important! The exitScene handler in view3 is called. Any code outside the createScene in view2 is executed - again. Then the code within the createScene in view2 in executed - again. This allows for the recreation of the Map and all other display elements. And finally the enterScene handler is triggered. Now here is where things get interesting. If I change the removeScene statement in view3 to purgeScene then I get the following in the Terminal when I navigate from view3 back to view 2:

2013-06-14 08:38:23.161 Corona Simulator[21447:707] view3: exitScene()

2013-06-14 08:38:23.162 Corona Simulator[21447:707] view2: createScene()

2013-06-14 08:38:23.163 Corona Simulator[21447:707] WARNING: Map views are not supported in the simulator. Please build for device.

2013-06-14 08:38:23.170 Corona Simulator[21447:707] view2: enterScene()

Whoa! None of the code OUTSIDE the createScene in view2 is being executed. If you defined any local variables outside the createScene they will still persist and be available inside the createScene handler BUT any local methods defined OUTSIDE the createScene handler WILL NOT be executed again. Something to remember. You may see some extra print statements in the code and the Terminal output that demonstrates this point.

Now what if I manually remove the Map (mapView:removeSelf()) after the transition from view2 to view3 or view1? You must recreate it either just before view2 enters or sometime after because the Map was removed due to the removeScene method.

Take a look at the code. Play around with it. I had trouble understanding Storyboard scenes and native widgets until I spent a day playing around with a simple app such as this.

Now this is what I normally do for apps that do not have a great number of display elements on each of the scenes. Removing and recreating the entire scene in larger apps or graphic intensive can introduce a noticeable delay when transitioning between scenes. This is just one in many ways to handle situations such as this.

How large or intensive will your app be? I hope this helps.