Enable Push Notification in XCode project by default?

When Unity project compiled, the generated XCode project doesn’t have Push Notification on.
What is the way to make it on by default after compile?
Do I have to create a postprocessing like the below?
If so, how?

I manage to get it working by a C# script, but since this build setting need an .entitlement file in your xcode project, first you will need to create a text file called [projectName].entitlement anywhere in your project with this content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>aps-environment</key>
  <string>development</string>
</dict>
</plist>

Now you can add this script on the Editor folder:

using System.IO;
using JetBrains.Annotations;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using UnityEngine;

public class PostProcessBuildScript : ScriptableObject
{
    public DefaultAsset entitlementsFile;

    [PostProcessBuild, UsedImplicitly]
    public static void ChangesToXcode(BuildTarget buildTarget, string pathToBuiltProject)
    {
        // Get project PBX file
        var projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
        var proj = new PBXProject();
        proj.ReadFromString(File.ReadAllText(projPath));
        var target = proj.TargetGuidByName("Unity-iPhone");

        // Create an instance of this ScriptableObject so we can point to its entitlements file
        var dummy = CreateInstance<PostProcessBuildScript>();
        var entitlementsFile = dummy.entitlementsFile;
        DestroyImmediate(dummy);
        if (entitlementsFile != null)
        {
            // Copy the entitlement file to the xcode project
            var entitlementPath = AssetDatabase.GetAssetPath(entitlementsFile);
            var entitlementFileName = Path.GetFileName(entitlementPath);
            var unityTarget = PBXProject.GetUnityTargetName();
            var relativeDestination = unityTarget + "/" + entitlementFileName;
            FileUtil.CopyFileOrDirectory(entitlementPath, pathToBuiltProject + "/" + relativeDestination);

            // Add the pbx configs to include the entitlements files on the project
            proj.AddFile(relativeDestination, entitlementFileName);
            proj.AddBuildProperty(target, "CODE_SIGN_ENTITLEMENTS", relativeDestination);

            // Add push notifications as a capability on the target
            proj.AddBuildProperty(target, "SystemCapabilities", "{com.apple.Push = {enabled = 1;};}");
        }

        // Save the changed configs to the file
        File.WriteAllText(projPath, proj.WriteToString());
    }
}

After that you just define the entitlementsFile variable for the script in the inspector window and you should now have the push notification activated by default when you build for iOS.

Just wanted to further develop @CelitoOokaIsland’s solution. I removed the need for a separate entitlements asset, and just embedded the string into the build script.

In theory, you should be able to drop this script into any project and have it work:

using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
using System.IO;
using UnityEditor.iOS.Xcode;

public class EntitlementsPostProcess
{
    private const string entitlements = @"
    <?xml version=""1.0"" encoding=""UTF-8\""?>
    <!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
    <plist version=""1.0"">
        <dict>
            <key>aps-environment</key>
            <string>development</string>
        </dict>
    </plist>";
    
    [PostProcessBuild]
    public static void OnPostProcess(BuildTarget buildTarget, string buildPath)
    {
        if (buildTarget != BuildTarget.iOS) return;

        var file_name = "unity.entitlements";
        var proj_path = PBXProject.GetPBXProjectPath(buildPath);
        var proj = new PBXProject();
        proj.ReadFromFile(proj_path);

        // target_name = "Unity-iPhone"
        var target_name = PBXProject.GetUnityTargetName();
        var target_guid = proj.TargetGuidByName(target_name);        
        var dst = buildPath + "/" + target_name + "/" + file_name;
        try
        {
            File.WriteAllText(dst, entitlements);
            proj.AddFile(target_name + "/" + file_name, file_name);
            proj.AddBuildProperty(target_guid, "CODE_SIGN_ENTITLEMENTS", target_name + "/" + file_name);
            proj.WriteToFile(proj_path);
        }
        catch (IOException e)
        {
            Debug.LogWarning($"Could not copy entitlements. Probably already exists. ({e})");
        }
    }
}