我在游戏中使用SharedObject来存储玩家在游戏中的进度(级别得分,解锁级别等)。

一切工作正常,但是问题是当我更新游戏(使用相同的证书以及相同的.swf.ipa文件的名称)时,当更新游戏时,旧的SharedObject被删除了,这对于我来说是一个很大的问题游戏和对我来说。

两种版本的游戏均使用Flash CS 6和Air SDK 3.5制作。

知道为什么删除SharedObject时,如何防止这种情况?

最佳答案

我假设SharedObject被覆盖的原因是因为它在转换过程中与.ipa bundle 在一起。

我了解这对挽救SharedObject不会有帮助,但您可以尝试使用flash.filesystem将数据读/写到首选项文件中,而不是将来使用SharedObject。

以下是我在自己的工作中使用的我的Archive类,但是我以前从未为iOS开发过,因此我不确定它是否可以像在其他部署目标上那样工作,尽管我相信应该如此。

用例:

//Imports
import com.mattie.data.Archive;
import com.mattie.events.ArchiveEvent;

//Constants
private static const PREF_CANVAS_VOLUME:String = "prefCanvasVolume";
private static const DEFAULT_VOLUME:Number = 0.5;

//Initialize Archive
private function initArchive():void
{
    archive = new Archive();
    archive.addEventListener(ArchiveEvent.LOAD, init);
    archive.load();
}

//Initialize
private function init(event:ArchiveEvent):void
{
    archive.removeEventListener(ArchiveEvent.LOAD, init);

    canvasVolume = archive.read(PREF_CANVAS_VOLUME, DEFAULT_VOLUME);
}

//Application Exiting Event Handler
private function applicationExitingEventHandler(event:Event):void
{
    stage.nativeWindow.removeEventListener(Event.CLOSING, applicationExitingEventHandler);

    archive.write(PREF_CANVAS_VOLUME, canvas.volume);

    archive.addEventListener(ArchiveEvent.SAVE, archiveSavedEventHandler);
    archive.save();
}

//Archive Saved Event Handler
private function archiveSavedEventHandler(event:ArchiveEvent):void
{
    archive.removeEventListener(ArchiveEvent.SAVE, archiveSavedEventHandler);

    NativeApplication.nativeApplication.exit();
}

Archive Class
package com.mattie.data
{
    //Imports
    import com.mattie.events.ArchiveEvent;
    import flash.data.EncryptedLocalStore;
    import flash.desktop.NativeApplication;
    import flash.events.EventDispatcher;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.net.registerClassAlias;
    import flash.utils.ByteArray;

    //Class
    public final class Archive extends EventDispatcher
    {
        //Properties
        private static var singleton:Archive;

        //Variables
        private var file:File;
        private var data:Object;

        //Constructor
        public function Archive()
        {
            if (singleton)
            {
                throw new Error("Archive is a singleton that is only accessible via the \"archive\" public property.");
            }

            file = File.applicationStorageDirectory.resolvePath(NativeApplication.nativeApplication.applicationID + "Archive");

            data = new Object();

            registerClassAlias("Item", Item);
        }

        //Load
        public function load():void
        {
            if (file.exists)
            {
                var fileStream:FileStream = new FileStream();
                fileStream.open(file, FileMode.READ);

                data = fileStream.readObject();

                fileStream.close();
            }

            dispatchEvent(new ArchiveEvent(ArchiveEvent.LOAD));
        }

        //Read
        public function read(key:String, defaultValue:* = null):*
        {
            var value:* = defaultValue;

            if (data[key] != undefined)
            {
                var item:Item = Item(data[key]);

                if (item.encrypted)
                {
                    var bytes:ByteArray = EncryptedLocalStore.getItem(key);

                    if (bytes == null)
                    {
                        return value;
                    }

                    switch (item.value)
                    {
                        case "Boolean":     value = bytes.readBoolean();                        break;
                        case "int":         value = bytes.readInt();                            break;
                        case "uint":        value = bytes.readUnsignedInt();                    break;
                        case "Number":      value = bytes.readDouble();                         break;
                        case "ByteArray":           bytes.readBytes(value = new ByteArray());   break;

                        default:            value = bytes.readUTFBytes(bytes.length);
                    }
                }
                else
                {
                    value = item.value;
                }
            }

            return value;
        }

        //Write
        public function write(key:String, value:*, encrypted:Boolean = false, autoSave:Boolean = false):void
        {
            var oldValue:* = read(key);

            if (oldValue != value)
            {
                var item:Item = new Item();
                item.encrypted = encrypted;

                if (encrypted)
                {
                    var constructorString:String = String(value.constructor);
                    constructorString = constructorString.substring(constructorString.lastIndexOf(" ") + 1, constructorString.length - 1);

                    item.value = constructorString;

                    var bytes:ByteArray = new ByteArray();

                    switch (value.constructor)
                    {
                        case Boolean:       bytes.writeBoolean(value);          break;
                        case int:           bytes.writeInt(value);              break;
                        case uint:          bytes.writeUnsignedInt(value);      break;
                        case Number:        bytes.writeDouble(value);           break;
                        case ByteArray:     bytes.writeBytes(value);            break;

                        default:            bytes.writeUTFBytes(value);
                    }

                    EncryptedLocalStore.setItem(key, bytes);
                }
                else
                {
                    item.value = value;
                }

                data[key] = item;

                dispatchEvent(new ArchiveEvent(ArchiveEvent.WRITE, key, oldValue, value));

                if (autoSave)
                {
                    save();
                }
            }
        }

        //Remove
        public function remove(key:String, autoSave:Boolean = false):void
        {
            if (data[key] != undefined)
            {
                var oldValue:* = read(key);

                if (Item(data[key]).encrypted)
                {
                    EncryptedLocalStore.removeItem(key);
                }

                delete data[key];

                dispatchEvent(new ArchiveEvent(ArchiveEvent.DELETE, key, oldValue));

                if (autoSave)
                {
                    save();
                }
            }
        }

        //Contains
        public function contains(key:String):Boolean
        {
            return (data[key] != undefined);
        }

        //Save
        public function save():void
        {
            var fileStream:FileStream = new FileStream();
            fileStream.open(file, FileMode.WRITE);
            fileStream.writeObject(data);
            fileStream.close();

            dispatchEvent(new ArchiveEvent(ArchiveEvent.SAVE));
        }

        //Get Singleton
        public static function get archive():Archive
        {
            if (!singleton)
            {
                singleton = new Archive();
            }

            return singleton;
        }
    }
}

//Item
class Item
{
    //Variables
    public var value:*;
    public var encrypted:Boolean = false;
}

Archive Event Class
package com.mattie.events
{
    //Imports
    import flash.events.Event;

    //Class
    public class ArchiveEvent extends Event
    {
        //Constants
        public static const LOAD:String = "load";
        public static const WRITE:String = "write";
        public static const DELETE:String = "delete";
        public static const SAVE:String = "save";

        //Properties
        public var key:String;
        public var oldValue:*;
        public var newValue:*;

        //Constructor
        public function ArchiveEvent(type:String, key:String = null, oldValue:* = null, newValue:* = null)
        {
            super(type);

            this.key = key;
            this.oldValue = oldValue;
            this.newValue = newValue;
        }

        //Clone
        public override function clone():Event
        {
            return new ArchiveEvent(type, key, oldValue, newValue);
        }

        //To String
        public override function toString():String
        {
            return formatToString("ArchiveEvent", "type", "key", "oldValue", "newValue");
        }
    }
}

09-16 07:43