Help us understand the problem. What is going on with this article?

Xcode設定自動化スクリプト

More than 1 year has passed since last update.

PBXProjectEditor.cs

PBXProjectEditor.cs
#if UNITY_IOS
/**
 * @file     PBXProjectEditor.cs
 * @brief    PBXプロジェクトの編集を行う。
 * @date     $Date$
 * @version  $Rev$
 * @author   $Author$
 */
using UnityEditor;
using UnityEditor.iOS.Xcode;
using System;
using System.IO;
using System.Collections.Generic;

namespace yyama2.Editor.XCProjEdit {

    /// <summary>
    /// PBXプロジェクトのプロパティを設定する。
    /// 
    /// 
    /// 設定は下記の様に定義してください。
    /// 
    /// ■file操作(追加・削除・移動) ※PBXParamFile.FileParam参照
    /// new List() {
    ///     new PBXParamFile.FileParam( 
    ///         type, 
    ///         fromDir, 
    ///         fromFile, 
    ///         toDir, 
    ///         toFile, 
    ///         compileFlag // 省略可
    ///     ),
    /// }
    /// 
    /// ■Framework ※PBXParamFramework参照
    /// new Dictionary<string, int>() {
    ///     { "value.framework", 1 },
    /// } 
    /// 
    /// ■Property設定 ※PBXParamProperty.PropertyParams参照
    /// new Dictionary<string, List<PBXParamProperty.PropertyParams>>() { 
    ///     "property", 
    ///     new List<PBXParamProperty.PropertyParams>() {
    ///         new PBXParamProperty.PropertyParams( 
    ///             configType:"config_type",          // configType
    ///             addValue:new string[]{ "YES" },  // AddValue
    ///             nremoveType:ew string[]{ "NO" },   // RemoveValue
    ///             forceOverride:false                   // 上書きフラグ
    ///         ), 
    ///     }
    /// },
    /// </summary>
    public static class PBXProjectEditor {

        /// <summary> Unityデフォルトのプロジェクト名(基本変更しなくていい)</summary>
        public const string NATIVE_TARGET_NAME = "Unity-iPhone";
        /// <summary> XcodeProjectの拡張子</summary>
        public const string XCODE_PROJ_FILE_EXTENSION = ".xcodeproj";
        /// <summary> XcodeProjectファイル</summary>
        public const string XCODE_PROJ_FILE = NATIVE_TARGET_NAME + XCODE_PROJ_FILE_EXTENSION;
        /// <summary> PBXプロジェクトファイル</summary>
        public const string PBX_PROJ_FILE = "project.pbxproj";

        /// <summary> project.pbxprojのパスを取得する</summary>
        /// <param name="path"> project.pbxprojのあるフォルダパス</param>
        /// <returns> project.pbxprojのファイルパス</returns>
        public static string GetDefaultPBXProjectPath( string path )
        {
            return Path.Combine( Path.Combine( path, XCODE_PROJ_FILE ), PBX_PROJ_FILE );
        }

        /// <summary>
        /// PBXプロジェクトの編集
        /// </summary>
        /// <param name="pbxProjPath">Pbx proj path.</param>
        /// <param name="pbxParams">Pbx parameters.</param>
        /// <param name="callClass">この関数を呼び出しているクラスタイプ.ログ出力に飲み使用します.typeof( クラス )</param>
        public static void PBXProjectEdit( string pbxProjPath, List<PBXParam> pbxParams, Type callClass = null )
        {
            string className = "";

            if( callClass != null )
            {
                className += callClass.Name;
            }
            UnityEngine.Debug.Log( "PBXProjectEditor:" + className );
            string log = "======================= PBXProjectValue =======================\n";
            UnityEngine.Debug.Log( "pbxProjPath=>" + pbxProjPath );
            PBXProject pbxProj = new PBXProject();
            pbxProj.ReadFromFile( pbxProjPath );

            foreach( PBXParam param in pbxParams )
            {
                param.Edit( ref pbxProj );
            }

            pbxProj.WriteToFile( pbxProjPath );

            log += className + "\n";
            foreach( PBXParam param in pbxParams )
            {
                log += param.GetParamLog();
            }

            log += "\n======================= PBXProjectValue =======================";
            UnityEngine.Debug.Log( log );
        }

    }

    /// <summary>
    /// 設定項目のクラス。 
    /// </summary>
    public abstract class PBXParam {
        /// <summary>
        /// 設定されているパラメータのログ。
        /// </summary>
        /// <returns>The parameter log.</returns>
        public abstract string GetParamLog();
        /// <summary>
        /// 設定の編集を行う
        /// </summary>
        /// <param name="pbxProj">Pbx projct.</param>
        public abstract void Edit( ref PBXProject pbxProj );

        /// <summary>
        /// プロジェクト名のリスト(基本的には、Unity-iPhoneのみ)
        /// </summary>
        /// <value>プロジェクト名一覧.</value>
        public string[] ProjectNames { get; protected set; }


        /// <summary>
        /// プロジェクトのguidを取得する。
        /// </summary>
        /// <returns>The project guids.</returns>
        /// <param name="pbxProj">Pbx project.</param>
        protected IEnumerable<string> GetProjectGuids( PBXProject pbxProj )
        {
            List<string> guids = new List<string>();
            foreach( string projectName in ProjectNames )
            {
                guids.Add( pbxProj.TargetGuidByName( projectName ) );
            }
            return guids;
        }

        /// <summary>
        /// コンストラクタ。継承先のクラスで必ず呼び出すこと( GetProjectGuids()で使用します。 )
        /// </summary>
        /// <param name="projectNames">Project names.</param>
        public PBXParam( string[] projectNames )
        {
            if( projectNames == null || projectNames.Length == 0 ) {
                projectNames = new []{ PBXProjectEditor.NATIVE_TARGET_NAME };
            }
            this.ProjectNames = projectNames;
        }
    }

    /// <summary>
    /// プロジェクトに設定されているファイルを追加するクラス。
    /// </summary>
    public class PBXParamFile : PBXParam {

        /// <summary> 編集を行うかどうか</summary>
        private readonly List<FileParam> m_params;

        /// <summary> Xcodeプロジェクトのディレクトリ</summary>
        private readonly string m_xcodePath;

        /// <summary>
        /// どのようなファイル操作を行うか。
        /// </summary>
        public enum FileEditType
        {
            /// <summary> ファイルの追加 </summary>
            ADD,
            /// <summary> ファイルのリネーム(移動)</summary>
            MOVE,
            /// <summary> ファイルの削除(物理削除は行わない)</summary>
            REMOVE,
        }

        /// <summary>
        /// 変更設定。
        /// </summary>
        public class FileParam {

            /// <summary> edit type.</summary>
            public FileEditType Type{ get; private set; }
            /// <summary> form directory path.</summary>
            public string FromDirPath{ get; private set; }
            /// <summary> from file name.</summary>
            public string FromFileName{ get; private set; }
            /// <summary> to directory path.</summary>
            public string ToDirPath{ get; private set; }
            /// <summary> to file name.</summary>
            public string ToFileName{ get; private set; }
            /// <summary> to file name.</summary>
            public string CompileFlags{ get; private set; }

            /// <summary>
            /// <para>指定するタイプによって引数の使い分けを行う。</para>
            /// <para></para>
            /// <para>ADD</para>
            /// <para>(Unityから自動で転送されないファイルをXcodeに転送してプロジェクトに追加する)</para>
            /// <para>_fromDir : Unity上(Assetsを除く)</para>
            /// <para>fromFile : Unity上のファイル名</para>
            /// <para>___toDir : Xcode上のディレクトリ</para>
            /// <para>__toFile : Xcode上のファイル名</para>
            /// <para></para>
            /// <para>MOVE</para>
            /// <para>(Xcode上からファイルを移動(リネーム)する)</para>
            /// <para>_fromDir : Xcode上で移動前のディレクトリ</para>
            /// <para>fromFile : Xcode上で移動前のファイル名</para>
            /// <para>___toDir : Xcode上で移動後のディレクトリ</para>
            /// <para>__toFile : Xcode上で移動後のファイル名</para>
            /// <para></para>
            /// <para>REMOVE</para>
            /// <para>(Xcode上からファイルを削除する)</para>
            /// <para>_fromDir : Xcode上のディレクトリ</para>
            /// <para>fromFile : Xcode上のファイル名</para>
            /// <para>___toDir : -</para>
            /// <para>__toFile : -</para>
            /// </summary>
            /// <param name="type">Type.</param>
            /// <param name="fromDir">From dir.</param>
            /// <param name="fromFile">From file.</param>
            /// <param name="toDir">To dir.</param>
            /// <param name="toFile">To file.</param>
            /// <param name="compileFlags">Compile Flags.</param>
            public FileParam( FileEditType type, string fromDir, string fromFile, string toDir = null, string toFile = null, string compileFlags = null )
            {
                if( type != FileEditType.REMOVE )
                {
                    string param = "";
                    bool isNull = false;
                    if( toDir == null )
                    {
                        param += "toDir";
                        isNull = true;
                    }
                    if( toFile == null )
                    {
                        if( isNull )
                        {
                            param += ", ";
                        }
                        param += "toFile";
                    }
                    if( isNull )
                    {
                        throw new System.ArgumentNullException( param, "If type is not REMOVE, you must set toXXX parameter!" );
                    }
                }
                this.Type           = type;
                this.FromDirPath    = fromDir;
                this.FromFileName   = fromFile;
                this.ToDirPath      = toDir;
                this.ToFileName     = toFile;
                this.CompileFlags   = compileFlags;
            }

            /// <summary>
            /// ログを作成.
            /// </summary>
            public string CreateLog()
            {
                string log = "[File:";

                switch( Type )
                {
                    case FileEditType.ADD:
                        log += "Add]" + "\n\tUnity file: " + CombinePath( FromDirPath, FromFileName ) + "\n\tXcode file: " + CombinePath( ToDirPath, ToFileName + "\n\tCompile flags: " + CompileFlags );
                        break;
                    case FileEditType.MOVE:
                        log += "Move]" + "\n\tXC before file: " + CombinePath( FromDirPath, FromFileName ) + "\n\tXC  after file: " + CombinePath( ToDirPath, ToFileName + "\n\tCompile flags: " + CompileFlags );
                        break;
                    case FileEditType.REMOVE:
                        log += "Delete]" + "\n\tDelete file: " + CombinePath( FromDirPath, FromFileName );
                        break;
                }
                return log;
            }
        }

        /// <summary>
        /// 設定されているパラメータのログ。
        /// </summary>
        /// <returns>The parameter log.</returns>
        public override string GetParamLog ()
        {
            string log = "";

            foreach( FileParam param in m_params )
            {
                log += param.CreateLog() + "\n";
            }
            return log;
        }

        /// <summary>
        /// 設定の編集を行う
        /// </summary>
        /// <param name="pbxProj">Pbx projct.</param>
        public override void Edit( ref PBXProject pbxProj )
        {
            foreach( FileParam param in m_params )
            {
                switch( param.Type )
                {
                case FileEditType.ADD:
                    {
                        // ファイルを追加する
                        AddFile( ref pbxProj, param );
                        break;
                    }
                case FileEditType.MOVE:
                    {
                        // ファイルのリネームや移動
                        MoveFile( ref pbxProj, param );
                        break;
                    }
                case FileEditType.REMOVE:
                    {
                        // ファイルの削除
                        RemoveFile( ref pbxProj, param );
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Unity上にはあるが、プロジェクトに追加されていないファイルをXcodeプロジェクトに追加する。
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="param">Parameter.</param>
        private void AddFile( ref PBXProject pbxProj, FileParam param )
        {
            // UnityのファイルをXcodeにコピーする
            string unityPath = CombinePath( UnityEngine.Application.dataPath, param.FromDirPath, param.FromFileName );
            string xcodePath = CombinePath( m_xcodePath, param.ToDirPath, param.ToFileName );
            CopyFile( unityPath, xcodePath );
            string addPath = CombinePath( param.ToDirPath, param.ToFileName );
            AddFileProc( ref pbxProj, addPath, param.CompileFlags );
        }

        /// <summary>
        /// Xcodeにファイルを追加する
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="addPath">Add path.</param>
        /// <param name="compileFlag">Compile flag.</param>
        private void AddFileProc( ref PBXProject pbxProj, string addPath, string compileFlag )
        {
            // ファイル参照をプロジェクトに追加
            pbxProj.AddFile( addPath, addPath );
            string fileGuid = pbxProj.FindFileGuidByProjectPath( addPath );

            // プロジェクトの設定(BuildPhase)に追加
            foreach( string guid in GetProjectGuids( pbxProj ) )
            {
                pbxProj.AddFileToBuildWithFlags( guid, fileGuid, compileFlag );
            }
        }

        /// <summary>
        /// Xcodeのファイルを移動(リネーム)する
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="param">Parameter.</param>
        private void MoveFile( ref PBXProject pbxProj, FileParam param )
        {
            string beforePath = CombinePath( param.FromDirPath, param.FromFileName );
            string afterPath  = CombinePath( param.ToDirPath, param.ToFileName );
            // 既存のファイルを削除
            RemoveFileProc( ref pbxProj, beforePath );

            // 既存のファイルのリネーム
            MoveFile( CombinePath( m_xcodePath, beforePath ), CombinePath( m_xcodePath, afterPath ) );

            // リネーム後ファイルの追加
            AddFileProc( ref pbxProj, afterPath, param.CompileFlags );
        }

        /// <summary>
        /// Xcodeに追加されているファイルの削除(物理削除は行わない)
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="param">Parameter.</param>
        private void RemoveFile( ref PBXProject pbxProj, FileParam param )
        {
            string removePath = CombinePath( param.FromDirPath, param.FromFileName ); 
            RemoveFileProc( ref pbxProj, removePath );
        }

        /// <summary>
        /// Xcodeに追加されているファイルの削除(物理削除は行わない)
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="removePath">Remove path.</param>
        private void RemoveFileProc( ref PBXProject pbxProj, string removePath )
        {
            if ( !pbxProj.ContainsFileByProjectPath( removePath ) ) return;

            string fileGuid = pbxProj.FindFileGuidByProjectPath( removePath );
            foreach( string guid in GetProjectGuids( pbxProj ) )
            {
                pbxProj.RemoveFileFromBuild( guid, fileGuid );
            }
            pbxProj.RemoveFile( fileGuid );
        }

        /// <summary>
        /// ファイルの親ディレクトリを作成する。
        /// </summary>
        /// <param name="filePath">File path.</param>
        public static void CreateParentDirectory( string filePath )
        {
            string[] files = filePath.Split( "/"[0] );

            string path = "";
            for( int i = 0; i < files.Length - 1; ++i )
            {
                path += "/" + files[i];
                if( !Directory.Exists( path ) )
                {
                    Directory.CreateDirectory( path );
                }
            }
        }
        /// <summary>
        /// ファイルをコピーする.
        /// </summary>
        /// <param name="fromFile">From file.</param>
        /// <param name="toFile">To file.</param>
        public static void CopyFile( string fromFile, string toFile )
        {
            CreateParentDirectory( toFile );
            FileUtil.CopyFileOrDirectory( fromFile, toFile );   
        }

        /// <summary>
        /// ファイルを移動(リネーム)する。
        /// </summary>
        /// <param name="fromFile">From file.</param>
        /// <param name="toFile">To file.</param>
        public static void MoveFile( string fromFile, string toFile )
        {
            CreateParentDirectory( toFile );
            FileUtil.MoveFileOrDirectory( fromFile, toFile );   
        }

        /// <summary>
        /// パスの結合
        /// </summary>
        /// <returns>The path.</returns>
        /// <param name="fileAndDir">File and dir.</param>
        public static string CombinePath( params string[] fileAndDir )
        {
            string root = fileAndDir[0];
            for( int i = 1; i < fileAndDir.Length; ++i )
            {
                root = Path.Combine( root, fileAndDir[i] );
            }
            return root;
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="parameters">Parameters.</param>
        /// <param name="xcodePath">Xcode path.</param>
        /// <param name="projectNames">Project names.</param>
        public PBXParamFile( List<FileParam> parameters, string xcodePath, params string[] projectNames ) : base ( projectNames )
        {
            m_params = parameters;
            m_xcodePath = xcodePath;
        }
    }

    /// <summary>
    /// Framework変更
    /// </summary>
    public class PBXParamFramework : PBXParam {

        /// <summary>
        /// Framework設定
        /// </summary>
        private readonly Dictionary<string, int> m_framemworks;

        /// <summary>
        /// ログ用の文字列作成
        /// </summary>
        /// <returns>The parameter log.</returns>
        public override string GetParamLog()
        {
            string log = "";
            foreach( KeyValuePair<string, int> framework in m_framemworks )
            {
                log += "[Framework] " + framework.Key + ": " + 
                ( 
                    ( framework.Value == -1 ) ? "Delete!!" : 
                    ( 
                        ( framework.Value == 1 ) ? "Optional" : "Required" 
                    )
                ) + "\n";
            }
            return log;
        }

        /// <summary>
        /// 設定の編集を行う
        /// </summary>
        /// <param name="pbxProj">Pbx projct.</param>
        public override void Edit( ref PBXProject pbxProj )
        {
            IEnumerable<string> guids = GetProjectGuids( pbxProj );
            foreach( string guid in guids )
            {
                foreach( KeyValuePair<string, int> framemwork in m_framemworks )
                {
                    if( framemwork.Value == -1 )
                        pbxProj.RemoveFrameworkFromProject( guid, framemwork.Key );
                    else
                        pbxProj.AddFrameworkToProject( guid, framemwork.Key, framemwork.Value == 1 );
                }
            }
        }

        /// <summary>
        /// コンストラクタ
        /// 
        /// new Dictionary<string, int>() {
        ///     { "value1", 0 }, // Required
        ///     { "value2", 1 }, // Optional
        ///     { "value3", -1 },// 削除
        /// } 
        /// </summary>
        /// <param name="framemworks">Framemworks.</param>
        /// <param name="projectNames">Project names.</param>
        public PBXParamFramework( Dictionary<string, int> framemworks, params string[] projectNames ) : base( projectNames )
        {
            this.m_framemworks = framemworks;
        }
    }

    /// <summary>
    /// プロパティ変更
    /// </summary>
    public class PBXParamProperty : PBXParam {

        /// <summary>
        /// プロパティ設定
        /// </summary>
        private readonly Dictionary<string, List<PropertyParams>> m_params;

        /// <summary>
        /// プロパティ設定項目
        /// </summary>
        public class PropertyParams {

            /// <summary> 設定を行うタイプ(Debug/Releaseなど) </summary>
            public string ConfigType { get; private set; }
            /// <summary> 追加する値</summary>
            public string[] AddValues { get; private set; }
            /// <summary> 削除する値</summary>
            public string[] RemoveValues { get; private set; }
            /// <summary> 既存の項目をむしして上書きするかどうか。</summary>
            public bool ForceOverride { get; private set; }

            /// <summary>
            /// コンストラクタ
            /// </summary>
            /// <param name="configType">設定を行うコンフィグのタイプ.nullの場合はすべての設定に反映されます.</param>
            /// <param name="addValue">追加する値の配列.</param>
            /// <param name="removeValue">削除する値の配列.</param>
            /// <param name="forceOverride">強制的に上書きを行うかどうか.</param>
            public PropertyParams( string[] addValue, string[] removeValue = null, string configType = null, bool forceOverride = false )
            {
                this.ConfigType     = configType;
                this.AddValues      = addValue;
                this.RemoveValues   = removeValue;
                this.ForceOverride  = forceOverride;
            }

            /// <summary>
            /// ログの作成
            /// </summary>
            /// <returns>The log.</returns>
            public string CraeteLog()
            {
                string add = "[";
                for( int i = 0; AddValues != null && i < AddValues.Length; ++i )
                {
                    add += AddValues[i];
                    if( AddValues.Length - 1 != i )
                    {
                        add += ",";
                    }
                }
                add += "]";

                string remove = "[";
                for( int i = 0; RemoveValues != null && i < RemoveValues.Length; ++i )
                {
                    remove += RemoveValues[i];
                    if( RemoveValues.Length - 1 != i )
                    {
                        remove += ",";
                    }   
                }
                remove += "]";

                return "\n\tConfig Type: " + ConfigType + "\n\tadd values: " + add + "\n\tremove values: " + remove;
            }
        }

        /// <summary>
        /// コンフィグ設定のguidを取得
        /// </summary>
        /// <returns>The config guids.</returns>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="configName">Config name.</param>
        private IEnumerable<string> GetConfigGuids( PBXProject pbxProj, string configName )
        {
            IEnumerable<string> projects = GetProjectGuids( pbxProj );
            List<string> guids = new List<string>();
            foreach( string guid in projects )
            {
                guids.Add( pbxProj.BuildConfigByName( guid, configName ) );
            }
            return guids;
        }

        /// <summary>
        /// ログの作成
        /// </summary>
        /// <returns>The parameter log.</returns>
        public override string GetParamLog()
        {
            string log = "";
            foreach( KeyValuePair<string, List<PropertyParams>> kv in m_params )
            {
                foreach( PropertyParams param in kv.Value )
                {
                    log += "[Property] " + kv.Key + ":" + param.CraeteLog() + "\n";
                }
            }
            return log;
        }

        /// <summary>
        /// 設定の編集を行う
        /// </summary>
        /// <param name="pbxProj">Pbx projct.</param>
        public override void Edit( ref PBXProject pbxProj )
        {
            foreach( KeyValuePair<string, List<PropertyParams>> param in m_params )
            {
                string key = param.Key;
                foreach( PropertyParams propertyItem in param.Value )
                {
                    IEnumerable<string> guids = propertyItem.ConfigType == null ? GetProjectGuids( pbxProj ) : GetConfigGuids( pbxProj, propertyItem.ConfigType );
                    // 既存設定を無視して上書き
                    if( propertyItem.ForceOverride )
                    {
                        int i = 0;
                        if( propertyItem.ConfigType == null )
                        {
                            foreach( string addValue in propertyItem.AddValues )
                            {
                                if( i == 0 )
                                    pbxProj.SetBuildProperty( guids, key, addValue );
                                else
                                    pbxProj.AddBuildProperty( guids, key, addValue );
                            }
                            ++i;
                        }
                        else
                        {
                            guids = GetConfigGuids( pbxProj, propertyItem.ConfigType );
                            foreach( string addValue in propertyItem.AddValues )
                            {
                                if( i == 0 )
                                    pbxProj.SetBuildPropertyForConfig( guids, key, addValue );
                                else
                                    pbxProj.AddBuildPropertyForConfig( guids, key, addValue );
                            }
                            ++i;
                        }
                    }
                    else
                    {
                        if( propertyItem.ConfigType == null )
                        {
                            pbxProj.UpdateBuildProperty( guids, key, propertyItem.AddValues, propertyItem.RemoveValues );
                        }
                        else
                        {
                            /* 
                                 * UpdateBuildPropertyForConfig( IEnumerator<string>, stirng, string[], string[] )
                                 * は内部的に、UpdateBuildProperty( string, string, string[], string[] )をコールしており、
                                 * UpdateBuildPropertyForConfig( string, string, string[], string[] )と挙動が異なるので、foreachでguidはループで指定する
                                 */
                            foreach( string guid in guids )
                            {
                                pbxProj.UpdateBuildPropertyForConfig( guid, key, propertyItem.AddValues, propertyItem.RemoveValues );
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="parameters">Parameters.</param>
        /// <param name="projectNames">Project names.</param>
        public PBXParamProperty( Dictionary<string, List<PropertyParams>> parameters, params string[] projectNames ) : base( projectNames )
        {
            this.m_params = parameters;
        }
    }

}
#endif

PlistEditor.cs

PlistEditor.cs
#if UNITY_IOS
/**
 * @file     PlistEditor.cs
 * @brief    plistの編集を行うクラス。
 * @date     $Date$
 * @version  $Rev$
 * @author   $Author$
 */
using UnityEditor.iOS.Xcode;
using System;
using System.IO;
using System.Collections.Generic;

namespace yyama2.Editor.XCProjEdit {

    /// <summary>
    /// plistの値を変更する。
    /// 
    /// 
    /// 値の設定は、下記のように定義してください。
    /// ※キーは任意の文字列です。
    /// 
    /// int 系のデータ
    /// { "int", 1 },
    /// boolean系の値
    /// { "bool", true },
    /// 文字列
    /// { "string", "string value" },
    /// 配列
    /// { "list", new List<object>() { 1, 2, 3 } },
    /// Dict
    /// { "dict", new Dictionary<string, object>() {
    ///         { "value1", "string value" },
    ///         { "value2", 1 },
    ///         { "value3", true },
    ///     } 
    /// },
    /// </summary>
    public class PlistEditor {

        /// <summary> Info.plistのパスを取得する</summary>
        /// <param name="path"> Info.plistのあるフォルダパス</param>
        /// <returns> Info.plistのファイルパス</returns>
        public static string GetInfoPlistPath( string path )
        {
            return Path.Combine( path, "Info.plist" );
        }

        /// <summary>
        /// plistを編集する。
        /// </summary>
        /// <param name="plistPath"> plistファイルパス</param>
        /// <param name="values">追加する値.</param>
        /// <param name="callClass">この関数を呼び出しているクラス.</param>
        public static void EditPlist( string plistPath, Dictionary<string, object> values, Type callClass )
        {
            string className = "";

            if( callClass != null )
            {
                className += callClass.Name;
            }
            UnityEngine.Debug.Log( "PlistEditor:" + className );
            string log = "======================= PlistValue =======================\n";
            UnityEngine.Debug.Log( "plistPath=>" + plistPath );
            PlistDocument plist = new PlistDocument();
            plist.ReadFromFile( plistPath );

            foreach( KeyValuePair<string, object> value in values )
            {
                setValue( value.Key, value.Value, ref plist.root );
            }

            // Documentsフォルダを共有可能にする
            plist.WriteToFile( plistPath );

            log += className + "\n";
            log += plistPath +"\n{";
            foreach( var value in values )
            {
                CreateLog( value.Key, value.Value, 0, ref log );
            }
            log += "\n}\n" + "======================= PlistValue =======================";
            UnityEngine.Debug.Log( log );
        }

        /// <summary>
        /// 値をセットする
        /// </summary>
        /// <param name="key"> キー.</param>
        /// <param name="value"> 値.</param>
        /// <param name="dict"> Dictオブジェクト.</param>
        private static void setValue( string key, object value, ref PlistElementDict dict )
        {
            bool validValue = true;
            Type type = value.GetType();

            // int .
            if( type == typeof(int) )
            {
                dict.SetInteger( key, (int)value );
            }
            // bool .
            else if( type == typeof(bool) )
            {
                dict.SetBoolean( key, (bool)value );
            }
            // string .
            else if( type == typeof(string) )
            {
                dict.SetString( key, (string)value );
            }
            // list
            else if( type == typeof(List<object>) )
            {
                PlistElementArray subArray;

                if( !tryGetValue<PlistElementArray>( key, dict, out subArray ) )
                {
                    subArray = dict.CreateArray( key );
                }

                List<object> list = (List<object>)value;
                foreach( object val in list )
                {
                    addValue( val, ref subArray );
                }
            }
            // dictionary
            else if( type == typeof(Dictionary<string, object>) )
            {
                PlistElementDict subDict;

                if( !tryGetValue<PlistElementDict>( key, dict, out subDict ) )
                {
                    subDict = dict.CreateDict( key );
                }

                Dictionary<string, object> dictionary = (Dictionary<string, object>)value;
                foreach( var dictItem in dictionary )
                {
                    setValue( dictItem.Key, dictItem.Value, ref subDict );
                }
            }
            else validValue = false;

            // invalid parameter
            if( !validValue )
            {
                UnityEngine.Debug.LogError( "Plist Editor.  Invalid Parameter => " + key );
            }
        }

        /// <summary>
        /// リストに値をセットする
        /// </summary>
        /// <param name="value">値.</param>
        /// <param name="array">Arrayオブジェクト.</param>
        private static void addValue( object value, ref PlistElementArray array )
        {
            Type type = value.GetType();

            // int .
            if( type == typeof(int) )
            {
                array.AddInteger( (int)value );
            }
            // bool .
            else if( type == typeof(bool) )
            {
                array.AddBoolean( (bool)value );
            }
            // string .
            else if( type == typeof(string) )
            {
                array.AddString( (string)value );
            }
            // list
            else if( type == typeof(List<object>) )
            {
                PlistElementArray subArray = array.AddArray();
                List<object> list = (List<object>)value;
                foreach( object val in list )
                {
                    addValue( val, ref subArray );
                }
            }
            // dictionary
            else if( type == typeof(Dictionary<string, object>) )
            {
                PlistElementDict subDict = array.AddDict();
                Dictionary<string, object> dictionary = (Dictionary<string, object>)value;
                foreach( var dictItem in dictionary )
                {
                    setValue( dictItem.Key, dictItem.Value, ref subDict );
                }
            }
            else
            {
                UnityEngine.Debug.LogError( "Add List Error!!" );
            }
        }

        /// <summary>
        /// dictオブジェクトから値を抽出する
        /// </summary>
        /// <returns><c>true</c>, if success to get, <c>false</c> otherwise.</returns>
        /// <param name="key">Key.</param>
        /// <param name="dict">Dictオブジェクト.</param>
        /// <param name="val">Value.</param>
        /// <typeparam name="T">The 1st type parameter.</typeparam>
        private static bool tryGetValue<T>( string key, PlistElementDict dict, out T val ) where T : PlistElement
        {
            IDictionary<string, PlistElement> dictValue = dict.values;
            PlistElement el;
            val = null;
            if( dictValue.TryGetValue( key, out el ) )
            {
                val = el as T;
            }
            return val != null;
        }

        /// <summary>
        /// ログ様の文字列作成 .
        /// </summary>
        /// <param name="key">Key.</param>
        /// <param name="value">Value.</param>
        /// <param name="indent">Indent.</param>
        /// <param name="log">Log.</param>
        private static void CreateLog( string key, object value, int indent, ref string log )
        {
            ++indent;
            string indentTabs = "";
            for( int i = 0; i < indent; ++i )
            {
                indentTabs += "\t";
            }
            log += "\n" + indentTabs + key + ":";
            Type type = value.GetType();
            // int .
            if( type == typeof(int) )
            {
                log += value;
            }
            // bool .
            else if( type == typeof(bool) )
            {
                log += value;
            }
            // string .
            else if( type == typeof(string) )
            {
                log += "\"" + value + "\"";
            }
            // list
            else if( type == typeof(List<object>) )
            {
                log += "[";
                List<object> list = (List<object>)value;
                for( int i = 0; i < list.Count; ++i )
                {
                    CreateLog( "["+ i +"]", list[i], indent, ref log);
                }
                log += "\n" + indentTabs + "]";
            }
            // dictionary
            else if( type == typeof(Dictionary<string, object>) )
            {
                Dictionary<string, object> dictionary = (Dictionary<string, object>)value;
                log += "{";         
                foreach( var dictItem in dictionary )
                {
                    CreateLog( dictItem.Key, dictItem.Value, indent, ref log );
                }

                log += "\n" + indentTabs + "}";
            }
            log += ",";
        }
    }
}
#endif
yyama2
Unity とAndroid やってます。 メモ書きばっかになりますすいません.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away