Code used to work, now doesn't...

Something has changed. I have an iPhone app out, and I decided to make it available on Android. Problem is, it no longer works. There are probably multiple problems, but the first one I came across is this:

Early in main.lua I have the lines:

background = display.newImage("menuscreen.png")  
menuScreen:insert( background )  

Later, within a function, I again have the line:

menuScreen:insert( background )  

But now it produces the error:

/Users/slg/Corona/Schism/main.lua:2515: bad argument #-2 to 'insert' (Proxy expected, got nil)  

I get at least one other error having to do with the variable background, this time on a “menuscreen: remove(background)” line. Basically, the same error message.

What do I need to do to make this work again?

Thanks,

Sean. [import]uid: 4993 topic_id: 2120 reply_id: 302120[/import]

could you send us some more code to look, send it to us at support @ anscamobile.com

or did the problem went away?

c. [import]uid: 24 topic_id: 2120 reply_id: 6361[/import]

The problem sounds like a scope issue. “background” is not within the scope of function when it’s inserted.

It’s hard to tell without seeing all of the code and how everything is defined.

-Tom [import]uid: 7559 topic_id: 2120 reply_id: 6571[/import]

It does sound like a scope issue, and further experimenting seems to point that way as well. Essentially, if I redefine the variable within the function, then it works.

But it doesn’t make sense to me.

“background” is declared early in the code and outside of any function. My understanding of Lua is that this causes a variable to be a global. As a global, it should be available to all functions, correct? Yet, the error show it isn’t.

I’d provide more code, but the source file is over 3100 lines. If I can figure out how to reduce it and keep the error, I will. But given the complexity of the app, I kinda doubt I’ll be able to.

Sean. [import]uid: 4993 topic_id: 2120 reply_id: 6578[/import]

sean

as far as i understand the original post, it doesn’t work on android. but does the code work when you try to build for iPhone?

if it works on iPhone and not on android, then I think I know why.

Will probably have an answer by the time you reply.

Me.

(hopefully not in the next 30 seconds :wink:

c

[import]uid: 24 topic_id: 2120 reply_id: 6579[/import]

If you define the object at the top of your file it should be visible in the function(s) that follows later in the file. Sometimes you need to define a “forward reference” for a object that will be used later.
local background – forward reference

You can check the scope of a variable/object using a well placed print statement:
print("background: " … tostring(background) )

If it prints “nil”, it’s not within scope or hasn’t been define yet.

-Tom
[import]uid: 7559 topic_id: 2120 reply_id: 6580[/import]

One more thought. Around Beta 8 (or was it Beta 7) we changed the way removed objects work. Before Beta 8 you could remove an object from a group and reuse the same object. Now when you remove an object, the object is changed from a Display Object (e.g., image in your case) to a simple Lua table (no display properties).

Are you removing the “background” object and expecting to reuse it again? You can move the object from group to group but if it’s removed, you need to recreate the object again.

This may explain why it once worked and now it doesn’t. (I’m assuming both Android and iPhone apps fail in the same way.)

-Tom [import]uid: 7559 topic_id: 2120 reply_id: 6583[/import]

I’m sorry I wasn’t clear in the initial message.

First: It no longer works at all… this isn’t a build issue, but an issue when ever I try to use the code.

My suspicion is that Tom’s last reply above is the one that is correct. I tried to go back and use earlier versions on the code, but none would run, saying they were out of date. Being able to say it worked in Beta 6 but not Beta 7 (the last I could test with) would probably have pointed out the error right away.

Yeah, in looking at the code, I do exactly that. I remove the background, and then try to re-insert it when needed.

So, am I understanding the correctly? If I do the following:

background = display.newImage("menuscreen.png")  
menuScreen:insert( background )  
menuScreen:remove( background )  

background is no longer valid?

Sean. [import]uid: 4993 topic_id: 2120 reply_id: 6587[/import]

When “background” is removed, it is no longer a Display Object and is converted to a simple Lua table. This was done to solve a memory issue caused by the memory used by display objects. The change recovers the Texture memory used (from the newImage in your example) right after the removable. Previously, Corona didn’t know if the object was going to be reused so the memory kept building, leading to memory leaks.

You could recreate “background” if you need it later or directly move it to another group (using another group:insert(background). You could also create a group and make it invisible and use it to keep frequency used objects. You need to balance memory usage and the time to recreate objects.

When you do remove an object, it’s a good idea to set the variable to “nil” so what’s left of the object (Lua table) gets GC’d by Lua.

A new tool to help you understand Texture memory usage is an API that was added in Beta 8.
system.getInfo(“textureMemoryUsed”)
It displays the number of bytes used for Display Objects.

-Tom

[import]uid: 7559 topic_id: 2120 reply_id: 6588[/import]

I find that very odd behavior. Maybe it’s Lua’s architecture – I’m really a C developer, been doing it for a *long* time, and I don’t really know Lua as much more than a scripting language.

I’ve been looking at menuScreen:insert(background) as essentially a function call. I’ve passed in the variable, and the function should get its own copy in a different place in memory, and therefore shouldn’t be touching my original.

So, I guess that isn’t the way it works.

Question: If the display object is no longer usable, why not just go ahead and set it to nil? (I’m not criticizing, just trying to understand.)

The solution’s clear now that I understand the issue. Instead of keeping it in one place, just init it before I make the call each time.

Thanks,

Sean. [import]uid: 4993 topic_id: 2120 reply_id: 6590[/import]

Lua objects are passed by reference so only one copy of the objects exists at one time. If you have a “copy” of the object, you only have a copy of a pointer to the same object. Inserting the object into a group and then setting the variable that was pointing to the object to nil, doesn’t remove the object.

Display objects are not automatically set to nil after being removed because they still may contain custom information set in the object. The custom information would be be accessible after the display properties of the object was removed. This is not a very common situation but may be useful in some situations.

Coming from the c/c++ world myself, it took some time getting my head around how Lua works under the hood.

-Tom [import]uid: 7559 topic_id: 2120 reply_id: 6592[/import]

I’m not sure I understand the whole scope issue here. Groups defined globally can’t be accessed as such, they need to be assigned to a local variable within the function to be used, is that it?

I was trying to make some of my display stuff more efficient but I ended up causing more damage than anything because of this scope oddity.

The way I understand, display objects are available globally, even if created from a local function, but groups act as described above?

So at the beginning of each function interacting with a group I need to:

LocalDisplayGroup = DisplayGroup;  

and then interact with the LocalDisplayGroup ?

I’m trying to have my main game screen use a variety of group, in order to keep display objects in the proper drawing order (or Z-index), instead of re-adding all objects every time I have to draw a new one that goes below some others. Is this a good way to go about doing that?

Really not sure if I understand correctly here.

Thanks. [import]uid: 4920 topic_id: 2120 reply_id: 6846[/import]

As far as scope is concerned groups and DisplayObjects have the same scope. You generally define groups outside of functions so they can be accessed later. DisplayObjects can be defined in a function and loaded into a group (defined outside the function). If the DisplayObject was defined as a local within the function, the variable goes away when function exits, but the DisplayObject is still “reachable” within the group (e.g., LocalDisplayGroup[1]). I called this a “headless” DisplayObject since the original variable that held the pointer to the DisplayObject is gone.

One example would be a function that displays a menu. You create a group to hold your menu assets and call a function to add DisplayObjects to the menu group. When it’s time to remove the menu you can do a removSelf() on the group and all the “children” of the group will also be removed along with the menu group.

DisplayObjects added to a group generally go to the top of the group and displayed on top of other objects in the group. You can also specify the “index” of where to insert the object. Inserting an object that is already in the group will move it to the top of the group.

-Tom [import]uid: 7559 topic_id: 2120 reply_id: 7048[/import]

So, is there any way to determine if a display object is still a display object? I’ve got a project that reuses display objects often, and it would be a lot easier to make the code work again if I could determine whether or not a particular object was still valid as a display object. [import]uid: 4993 topic_id: 2120 reply_id: 7178[/import]

You can determine if a display object is still valid by testing the x parameter. If it’s nil, it’s no longer a display object.

if object.x == nil then  
 print("Not a display object")  
 do something ...  
end  

This is a different subject then the scope issue we talked about above.

-Tom [import]uid: 7559 topic_id: 2120 reply_id: 7183[/import]

For whatever it is worth - I see a lot of this on the simulator, but never on real devices…

I was driving myself crazy trying to fix the problem on an app I build using the first generation viewController/scrollView code.

I tried building for device on a whim… and viola’ - no more problem.

Currently using release 714 - but earlier builds had same effect.

[import]uid: 9070 topic_id: 2120 reply_id: 89115[/import]