Page 1 of 1

Good new way to save data and interface

Posted: Thu Nov 07, 2013 3:29 pm
by doobox
Hi there,

I set about creating an app some time ago that allowed a user to add interface elements as they used the app.
So for example they could click "New Button" and the app would create a new group of objects and place them in the interface for the user to interact with. Each object has data associated with it.

My issue was finding a way to save the user created interface when the app closed and restoring it when the app re-opened.
I looked at various methods found here in the forum but none seemed appropriate for an iOS app long term.
It looked like i was going to have to do things the hard way and iterate over every element on save storing every piece of data about each element (and there is a lot) to text or database file.

Today i found a solution that works for me, and thought i would share it as i have not seen the like spoke about anywhere before.


Step 1) I have used this method before to store custom properties in a separate stack on save and re-instate them on start-up.

Code: Select all

global tDataStackPath
on preOpenStack
   put specialFolderPath("documents") into tDataStackPath
   put tDataStackPath & "/data.livecode" into tDataStackPath
      
   if not (there is a file tDataStackPath) then
      create stack "myDataStack"
      put it into temp
      set the visible of temp to false
      set the filename of temp to tDataStackPath
      save temp
      go stack "MyMainStackNameHere"
   end if
   restoreMyCardFromDataStack // i will come to this in a moment
end preOpenStack
Now we have created a new stack at the location : tDataStackPath
Called : myDataStack
In the past i have stored data like custom properties to this stack like this...

Include the global variable at the top of any object, card or stack you are going to refer to the data stack

Code: Select all

global tDataStackPath
Now setting a custom property of the data stack is like this :

Code: Select all

set the username of stack tDataStackPath to "Happy Harry"
You can save the data stack now or in the on shutdown handler like :

Code: Select all

save stack tDataStackPath
You can obviously get that data back from the data stack at any time like :

Code: Select all

put the username of stack tDataStackPath into tUserName
But heres the thing...
Instead of me iterating over possibly thousands of elements and data i want to save at shutdown (headache).
I can use this method now :

step 2)

I save all my custom properties right into the object they belong to in the main stack (intuitive).
Now on shutdown i do this :

Code: Select all

command saveMyCardToDataStack
   copy card "myCard" of this stack to stack tDataStackPath
   delete the first card of stack tDataStackPath
end saveMyCardToDataStack

command restoreMyCardFromDataStack
   copy card "myCard" of stack tDataStackPath to this stack
   delete the first card of this stack
end restoreMyCardFromDataStack

on shutdown
   saveMyCardToDataStack
   save stack tDataStackPath
end shutdown
And remember we are restoring the card from the data stack in the preOpenCard handler above.

This means that the card in its entirety, all objects scripts and custom properties of the objects are saved and restored properly with quite minimal effort, it's quite seamless.
Hopefully i don't find issue with this method, because i love love love it :-)

Re: Good new way to save data and interface

Posted: Thu Nov 07, 2013 4:06 pm
by FourthWorld
That should work well. Stack files make excellent storage containers, both for UI elements and even just for data using custom props. I use stack files for a lot of data storage because the prop arrays are convenient, fast, and robust, and I don't have to invent a new partitioned format or a parser for it. :)

Re: Good new way to save data and interface

Posted: Thu Nov 07, 2013 6:41 pm
by Klaus
Hi Gary,

you might want to read this one:
http://forums.runrev.com/phpBB2/viewtop ... 714#p79718
:D


Best

Klaus

Re: Good new way to save data and interface

Posted: Thu Nov 07, 2013 7:41 pm
by doobox
I am working with an IOS app.
The data stack is created in the documents folder and is not a sub-stack (allowed on iOS)
All the action starts and ends in the main stack. The only way to do it in app store i think. I don't think your allowed to launch external code from within the standalone.

Re: Good new way to save data and interface

Posted: Thu Nov 07, 2013 8:00 pm
by doobox
I was thinking about how id go about updating this app via the app store.

For example i may want to have a new titlebar style in the update for arguments sake.
As it stands, when i user downloads the update with the new title bar and launches the app, they would of course see the old title bar, because the app would still load the saved card from the data stack.

So....

I can change the name of my card in the update from "myCard" to "myCardV2"

Put this updated preOpenStack handler in the stack :

Code: Select all

if there is a group "main" of stack tDataStackPath then // this can check for any object you expect to exist
      put the short name of the first card of stack tDataStackPath into tSavedCardName
      put the short name of the first card of this stack into tThisCardName
      if not(tThisCardName is tSavedCardName) then
         cleanUpTheSavedCardProgmatically
      end if
      restoreMyCardFromDataStack
   end if
Now when the updated app runs it will detect the card names don't match and allow you to run a command where you can alter the appearance of the saved card before it loads :-)

Code: Select all

command cleanUpTheSavedCardProgmatically
   // do your ammendments
end cleanUpTheSavedCardProgmatically

Re: Good new way to save data and interface

Posted: Thu Nov 07, 2013 9:46 pm
by Klaus
Hi Gary,

I did not say that this would be the solution to everything, just wanted to mention it 8)


Best

Klaus

Re: Good new way to save data and interface

Posted: Fri Nov 08, 2013 3:47 pm
by dave.kilroy
Thanks Gary - what you've done is a nice tweak of the 'splash' app approach that allows for user data to be preserved when the app is updated

I'm working on a system (on and off) where one app has to be able to 'send' uniquely designed checklists to associated iOS and Android apps (or to 'send' the data which will allow the mobile apps to create any required checklist). These checklists of course include checkboxes and other controls, and I will be sending simple text data (rather than stacks) which would go in a local SQLite database (in the 'Documents' folder) of the mobile apps. When the mobile apps launch they check for any newly arrived data, update the database if necessary, and then go on to query the database to create and display the last used checklist. I can then use a derived tables in the database to store responses once the checklist has been completed and send just the responses in text form back to the originating desktop app.

I thought about and rejected using stacks as data stores because of the small number of controls involved in each checklist, the requirement to send data back, and not wanting to send actual stacks back and forth.

But I like your approach and I may well use it in another situation :)

Re: Good new way to save data and interface

Posted: Sun Jan 26, 2014 12:34 pm
by sirobchGA0cda
Hello,
I want to translate my application into another language.
I use the "Custom Properties" function in Stack Property Inspector.
I try this method to saves the custom properties.
on Mac it works.
But when I launch the application in IO, it does not keep the last configuration.
For several days I 'trying several methods forum or tutorial on the web, but I can not do it, I can not save these datas or custom properties.
I admit that this is starting to discourage me.
I attach my code if someone can help me :
In my stack :

Code: Select all

lobal tDataStackPath
on preOpenStack
   put specialFolderPath("documents") into tDataStackPath
   put tDataStackPath & "/data.livecode" into tDataStackPath
      
   if not (there is a file tDataStackPath) then
      create stack "myDataStack"
      put it into temp
      set the visible of temp to false
      set the filename of temp to tDataStackPath
      save temp
      go stack "MyMainStackNameHere"
   end if
   restoreMyCardFromDataStack // i will come to this in a moment
end preOpenStack




command saveMyCardToDataStack
   copy card "myCard" of this stack to stack tDataStackPath
   delete the first card of stack tDataStackPath
end saveMyCardToDataStack

command restoreMyCardFromDataStack
   copy card "myCard" of stack tDataStackPath to this stack
   delete the first card of this stack
end restoreMyCardFromDataStack

on shutdown
   saveMyCardToDataStack
   save stack tDataStackPath
in one button :

Code: Select all

global tDataStackPath
on mouseUp
   set the customPropertySet of this stack to "Anglais"
   set the label of btn "b1" of cd 1 to the b1 of this stack
end mouseUp

Thanks in advance for helping.
Best regards
Boris

Re: Good new way to save data and interface

Posted: Sun Jan 26, 2014 12:56 pm
by endernafi
Gary,

First, thanks for sharing your knowledge; it'll be quite useful for many of us.

But, have you any apps using this technique published;
I wonder Apple's approach to it.
As far as I know, they are pretty sensitive about auxiliary executables;
and any kind of Livecode stack is *executable* for them, even if it's used as a data model.


~ Ender Nafi

Re: Good new way to save data and interface

Posted: Sun Jan 26, 2014 1:22 pm
by doobox
Hi Ender,

Yes, my latest app "Fav" : http://www.doobox.co.uk/fav/fav.html
Uses this technique.

Re: Good new way to save data and interface

Posted: Sun Jan 26, 2014 1:24 pm
by endernafi
Excellent, thank you.

I have *Fav*, btw.
It's a fine app; congrats.


~ Ender

Re: Good new way to save data and interface

Posted: Sun Jan 26, 2014 1:38 pm
by dave.kilroy
hi sirobchGA0cda

I've never tried creating a stack on an iOS device, maybe create a blank data.livecode stack on your mac, include it in the app bundle and then on first launch of your app on the iOS device copy it over to the documents folder - and then try pulling data from and saving to that copy.

Re: Good new way to save data and interface

Posted: Sun Jan 26, 2014 1:47 pm
by sirobchGA0cda
Hi Dave,
I tried your solution, it does not work.
My apllication does not keep in memory the custom properties.
I'm wrong somewhere but I do not know where.
Thanks for your help.
Boris

Re: Good new way to save data and interface

Posted: Sun Jan 26, 2014 2:37 pm
by Klaus
Hi Boris,

did you eventually password protect your stack(s)?
That prevents objects from being copied to/from that stack.

Or you can add some answer dialogs and check THE RESULT, which should be empty on success,
to find out WHERE exacrtly something fails:

Code: Select all

...
 if not (there is a file tDataStackPath) then
      create stack "myDataStack"

      answer "Create stack:" && the result
      put it into temp
      set the visible of temp to false
      set the filename of temp to tDataStackPath
      save temp
      answer "Save stack:" && the result

      go stack "MyMainStackNameHere"
   end if
## etc. Until you see WHERE it fails...
...
And it wouldn't have hurt to open a new thread for your problem 8)

Best

Klaus

Re: Good new way to save data and interface

Posted: Sun Jan 26, 2014 2:56 pm
by sirobchGA0cda
Thanks Klaus,
I'll test your proposal and following your advice to open a new thread if I can not find the solution.
Best regards
Boris