In building an iPhone app, XCode requires you use a loading storyboard or a loading image. As there are still some major bugs with the storyboard mechanism, safe area padding, using an image asset is a much more supported approach. The problem is that the developer has to support it. In order to do that, a correct asset has to be made in the Assets.xcassets sub-folder along with a Contents.json file that looks like this:
{
  "images" : [
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "2688h",
      "filename" : "LoadingX_1242w2688h.png",
      "minimum-system-version" : "12.0",
      "orientation" : "portrait",
      "scale" : "3x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "2688h",
      "filename" : "LoadingX_2688w1242h.png",
      "minimum-system-version" : "12.0",
      "orientation" : "landscape",
      "scale" : "3x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "1792h",
      "filename" : "LoadingX_828w1792h.png",
      "minimum-system-version" : "12.0",
      "orientation" : "portrait",
      "scale" : "2x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "1792h",
      "filename" : "LoadingX_1792w828h.png",
      "minimum-system-version" : "12.0",
      "orientation" : "landscape",
      "scale" : "2x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "2436h",
      "filename" : "LoadingX_1125w2436h.png",
      "minimum-system-version" : "11.0",
      "orientation" : "portrait",
      "scale" : "3x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "2436h",
      "filename" : "LoadingX_2436w1125h.png",
      "minimum-system-version" : "11.0",
      "orientation" : "landscape",
      "scale" : "3x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "736h",
      "filename" : "LoadingX_1242w2208h.png",
      "minimum-system-version" : "8.0",
      "orientation" : "portrait",
      "scale" : "3x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "736h",
      "filename" : "LoadingX_2208w1242h.png",
      "minimum-system-version" : "8.0",
      "orientation" : "landscape",
      "scale" : "3x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "667h",
      "filename" : "LoadingX_750w1334h.png",
      "minimum-system-version" : "8.0",
      "orientation" : "portrait",
      "scale" : "2x"
    },
    {
      "orientation" : "portrait",
      "idiom" : "iphone",
      "filename" : "LoadingX_640w960h.png",
      "extent" : "full-screen",
      "minimum-system-version" : "7.0",
      "scale" : "2x"
    },
    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "retina4",
      "filename" : "LoadingX_640w1136h.png",
      "minimum-system-version" : "7.0",
      "orientation" : "portrait",
      "scale" : "2x"
    },
    {
      "orientation" : "portrait",
      "idiom" : "iphone",
      "filename" : "LoadingX_320w480h.png",
      "extent" : "full-screen",
      "scale" : "1x"
    },
    {
      "orientation" : "portrait",
      "idiom" : "iphone",
      "filename" : "LoadingX_640w960h.png",
      "extent" : "full-screen",
      "scale" : "2x"
    },
    {
      "orientation" : "portrait",
      "idiom" : "iphone",
      "filename" : "LoadingX_640w1136h.png",
      "extent" : "full-screen",
      "subtype" : "retina4",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}
Let's define a structure in C# that can provide this information...
using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
struct ContentAsset
{
	public System.Drawing.Size Size;
	public int Scale;
	public string Extent;
	public string Orientation;
	public string MinimumSystemVersion;
	public string SubType;
	public string Device;
}
The goal is not to take an arbitrary image and stretch it to cover the required area without changing aspect ratio. Again, we turn to C# code...
public static partial class SystemDrawingFunctions
{
	/// <summary>
	///     Scales an image filling a size
	/// </summary>
	/// <param name="image">The image.</param>
	/// <param name="size">The size.</param>
	/// <param name="fitAspect">if set to <c>true</c> [fit aspect].</param>
	/// <returns>A new image of the desired size</returns>
	public static System.Drawing.Image ScaledToFill(
		this System.Drawing.Image image,
		System.Drawing.Size size,
		bool fitAspect = true)
	{
		double destX = 0;
		double destY = 0;
		double scaleRatio = 1;
		double scaleX = ((double)size.Width / (double)image.Width);
		double scaleY = ((double)size.Height / (double)image.Height);
		if (!fitAspect)
		{
			scaleRatio = Math.Min(scaleY, scaleX);
		}
		else
		{
			scaleRatio = Math.Max(scaleY, scaleX);
			destY = (size.Height - image.Height * scaleRatio) / 2;
			destX = (size.Width - image.Width * scaleRatio) / 2;
		}
		int destWidth = (int)Math.Round(image.Width * scaleRatio);
		int destHeight = (int)Math.Round(image.Height * scaleRatio);
		System.Drawing.Bitmap returnImage = new System.Drawing.Bitmap(size.Width, size.Height);
		using (System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(returnImage))
		{
			graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
			graphic.CompositingQuality = CompositingQuality.HighQuality;
			graphic.SmoothingMode = SmoothingMode.HighQuality;
			Rectangle to = new System.Drawing.Rectangle(
				(int)Math.Round(destX), (int)Math.Round(destY),
				destWidth, destHeight);
			Rectangle from = new System.Drawing.Rectangle(0, 0, image.Width, image.Height);
			graphic.DrawImage(image, to, from, System.Drawing.GraphicsUnit.Pixel);
			return returnImage;
		}
	}
	/// <summary>
	///     Converts  System.Drawing.Image to a byte array.
	/// </summary>
	/// <param name="image">The image.</param>
	/// <returns>a raw byte array</returns>
	public static byte[] ToByteArray(this System.Drawing.Image image)
	{
		using (var ms = new MemoryStream())
		{
			image.Save(ms, image.RawFormat);
			return ms.ToArray();
		}
	}
	/// <summary>
	///     Scales an image byte array to fill.
	/// </summary>
	/// <param name="image">The image.</param>
	/// <param name="width">The width.</param>
	/// <param name="height">The height.</param>
	/// <param name="fitAspect">if set to <c>true</c> [fit aspect].</param>
	/// <returns>a raw byte array of the scaled image</returns>
	public static byte[] ScaledToFill(
		this byte[] image,
		int width = 196,
		int height = 196,
		bool fitAspect = true)
	{
		using (var ms = new MemoryStream(image))
		{
			return Image.FromStream(ms).ScaledToFill(new Size(width, height)).ToByteArray();
		}
	}
}
Now we can build out the list of images to generate, and get to work!
// Pick a sample image off the desktop
var img = @"C:\Users\admin\Desktop\imageToResize\LaunchImage.png";
var fi = new FileInfo(img);
using (var image = System.Drawing.Image.FromFile(img, true))
{
	var sizes = new ContentAsset[] {
	new ContentAsset(){ Size = new System.Drawing.Size(1242, 2688),
		Orientation="portrait", Extent="full-screen", Scale=3, SubType="2688h",
		MinimumSystemVersion ="12.0", Device ="iPhone Xs Max" },
	new ContentAsset(){ Size = new System.Drawing.Size(2688, 1242),
		Orientation="landscape", Extent="full-screen", Scale=3, SubType="2688h",
		MinimumSystemVersion ="12.0", Device ="iPhone Xs Max" },
	new ContentAsset(){ Size = new System.Drawing.Size(828, 1792),
		Orientation="portrait", Extent="full-screen", Scale=2, SubType="1792h",
		MinimumSystemVersion ="12.0", Device ="iPhone Xr Max" },
	new ContentAsset(){ Size = new System.Drawing.Size(1792, 828),
		Orientation ="landscape", Extent="full-screen", Scale=2, SubType="1792h",
		MinimumSystemVersion ="12.0", Device ="iPhone Xr Max" },
	new ContentAsset(){ Size = new System.Drawing.Size(1125, 2436),
		Orientation="portrait", Extent="full-screen", Scale=3, SubType="2436h",
		MinimumSystemVersion ="11.0", Device ="iPhone X" },
	new ContentAsset(){ Size = new System.Drawing.Size(2436, 1125),
		Orientation="landscape", Extent="full-screen", Scale=3, SubType="2436h",
		MinimumSystemVersion ="11.0", Device ="iPhone X Landscape" },
	new ContentAsset(){ Size = new System.Drawing.Size(1242, 2208),
		Orientation="portrait", Extent="full-screen", Scale=3, SubType="736h",
		MinimumSystemVersion ="8.0", Device ="iPhone 6s Plus - 8 Plus" },
	new ContentAsset(){ Size = new System.Drawing.Size(2208, 1242),
		Orientation="landscape", Extent="full-screen", Scale=3, SubType="736h",
		MinimumSystemVersion ="8.0", Device ="Retina HD 5.5" },
	new ContentAsset(){ Size = new System.Drawing.Size(750,1334), Extent="full-screen",
		Scale =2, SubType="667h", MinimumSystemVersion="8.0", Device ="iPhone 6s - 8" },
	new ContentAsset(){ Size = new System.Drawing.Size(640,960),
		Orientation="portrait", Extent="full-screen", Scale=2,
		MinimumSystemVersion ="7.0",  Device ="iPhone 4, 4s" },
	new ContentAsset(){ Size = new System.Drawing.Size(640,1136),
		Orientation="portrait", Extent="full-screen", Scale=2, SubType="retina4",
		MinimumSystemVersion ="7.0", Device ="iPhone 5, 5c, 5s" },
	new ContentAsset(){ Size = new System.Drawing.Size(320,480),
		Orientation="portrait", Extent="full-screen", Scale=1, Device ="iPhone 1g-3Gs" },
	new ContentAsset(){ Size = new System.Drawing.Size(640,960),
		Orientation="portrait", Extent="full-screen", Scale=2, Device ="iPhone 4, 4s" },
	new ContentAsset(){ Size = new System.Drawing.Size(640, 1136),
		Orientation="portrait", Extent="full-screen", Scale=2, SubType="retina4", Device ="Retina 4" }
		/// No longer used
		/*
		new ContentAsset(){ Size = new System.Drawing.Size(768,1024), Device ="iPad, iPad 2, Mini" },
		new ContentAsset(){ Size = new System.Drawing.Size(1024,768), Device ="iPad Landscape" },
		new ContentAsset(){ Size = new System.Drawing.Size(1536,2048), Device ="iPad Retina" },
		new ContentAsset(){ Size = new System.Drawing.Size(2048,1536), Device ="12.9\" iPad Pro" },
		*/
	};
	foreach (var size in sizes)
	{
		var newImage = ScaledToFill(image, size.Size);
		try
		{
			newImage.Save(Path.Combine(fi.DirectoryName,
				"LoadingX_" + size.Size.Width + "w" + size.Size.Height + "h" + fi.Extension));
		}
		catch { }
	}
	// This matches the Contents.json file generated above
}
 
The entire output directory can be zipped, then unzipped into the appropriate .loadingxcassets folder. XCode will recognize it as a loading image - with every component populated correctly.
