<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: UIKit_Ninja</title>
    <description>The latest articles on DEV Community by UIKit_Ninja (@uikit_ninja).</description>
    <link>https://dev.to/uikit_ninja</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3572287%2F957d92a4-e560-4856-ba33-7ea9aff5f379.png</url>
      <title>DEV Community: UIKit_Ninja</title>
      <link>https://dev.to/uikit_ninja</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/uikit_ninja"/>
    <language>en</language>
    <item>
      <title>2026 iTMSTransporter Windows IPA Upload and Release Tutorial</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Wed, 23 Sep 2026 10:30:06 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/2026-itmstransporter-windows-ipa-upload-and-release-tutorial-34g1</link>
      <guid>https://dev.to/uikit_ninja/2026-itmstransporter-windows-ipa-upload-and-release-tutorial-34g1</guid>
      <description>&lt;h1&gt;
  
  
  2026 iTMSTransporter Windows IPA Upload and Release Tutorial
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;To upload an IPA on Windows with Apple's official iTMSTransporter, the correct command in 2026 looks like this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;iTMSTransporter&lt;/span&gt; &lt;span class="na"&gt;-m &lt;/span&gt;&lt;span class="kd"&gt;upload&lt;/span&gt; &lt;span class="na"&gt;-assetFile &lt;/span&gt;&lt;span class="kd"&gt;App&lt;/span&gt;.ipa &lt;span class="na"&gt;-assetDescription &lt;/span&gt;&lt;span class="kd"&gt;AppStoreInfo&lt;/span&gt;.plist &lt;span class="na"&gt;-u &lt;/span&gt;&lt;span class="kd"&gt;dev&lt;/span&gt;@example.com &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="kd"&gt;abcd&lt;/span&gt;&lt;span class="na"&gt;-efgh-ijkl-mnop
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;-assetDescription AppStoreInfo.plist&lt;/code&gt; in there — &lt;strong&gt;it is mandatory on Windows and Linux&lt;/strong&gt;, and officially this file can only be exported from Xcode. This is exactly where I got stuck, so below I'll explain how to generate it directly on Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, understand what changed in 2026
&lt;/h2&gt;

&lt;p&gt;If you follow tutorials from a few years ago, you will most likely fail. Three things have changed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-f&lt;/code&gt; can no longer be used to upload apps.&lt;/strong&gt; Apple has made it clear: uploading or verifying an app must use &lt;code&gt;-assetFile&lt;/code&gt;; &lt;code&gt;-f&lt;/code&gt; is retained only for other content types. The old &lt;code&gt;-m upload -f App.ipa&lt;/code&gt; style now fails outright.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.itmsp&lt;/code&gt; package delivery is deprecated.&lt;/strong&gt; In the past you had to manually create a &lt;code&gt;&amp;lt;vendor_id&amp;gt;.itmsp&lt;/code&gt; directory and drop &lt;code&gt;metadata.xml&lt;/code&gt; and the IPA into it; now you just point &lt;code&gt;-assetFile&lt;/code&gt; at the IPA. Much simpler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-assetDescription&lt;/code&gt; is required on Windows / Linux.&lt;/strong&gt; Apple's official user guide states it plainly: this parameter is "required for Linux and Windows App uploads, but not for macOS App uploads." On macOS you don't need it, because Transporter invokes the tools inside Xcode to generate one on the fly; on Windows there is no Xcode, so you have to prepare it yourself and hand it over.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Point 3 is the killer, so we'll handle it in a dedicated step below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install iTMSTransporter
&lt;/h2&gt;

&lt;p&gt;Transporter is currently at version &lt;strong&gt;4.2&lt;/strong&gt;, and the Windows build is a self-extracting installer.&lt;/p&gt;

&lt;p&gt;Download URL (official Apple direct link):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/resources/download/public/Transporter__Windows/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The download is &lt;code&gt;iTMSTransporterToolInstaller_4.2.0.&amp;lt;build&amp;gt;.exe&lt;/code&gt;. Double-click it, accept the license agreement, and the default install directory is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;C&lt;/span&gt;:\Program &lt;span class="kd"&gt;Files&lt;/span&gt;\itms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, an &lt;code&gt;iTMSTransporter.woa&lt;/code&gt; subdirectory is created inside. The command-line entry point lives in the install directory, written in the official docs as &lt;code&gt;.\iTMSTransporter&lt;/code&gt; (on Windows it is actually a batch script of the same name). If you're not sure where it is, search for &lt;code&gt;iTMSTransporter&lt;/code&gt; in the install directory.&lt;/p&gt;

&lt;p&gt;First verify that it runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"C:\Program Files\itms\bin"&lt;/span&gt;
&lt;span class="kd"&gt;iTMSTransporter&lt;/span&gt; &lt;span class="na"&gt;-version
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it prints a version number, the installation is fine. To make later commands easier to type, it is recommended to add this &lt;code&gt;bin&lt;/code&gt; directory to the system &lt;code&gt;PATH&lt;/code&gt;: Settings → System → About → Advanced system settings → Environment Variables → select Path → Edit → New, paste the directory path, then &lt;strong&gt;open a new command-line window&lt;/strong&gt; for it to take effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Prepare AppStoreInfo.plist (the critical step)
&lt;/h2&gt;

&lt;p&gt;This is where Windows users really get stuck, so let's first be clear about what it is.&lt;/p&gt;

&lt;p&gt;AppStoreInfo.plist is not a configuration file in your project; it is &lt;strong&gt;a descriptive manifest of your package&lt;/strong&gt;: the package type, platform, the structure of each bundle inside, icons, signing information, and so on. Apple relies on it to check the package when it is received. Apple itself wrote a line in the file:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This App Store Information can be used with iTMSTransporter and App Store Connect Developer API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem is that this manifest is normally generated by a tool in the Xcode toolchain, &lt;strong&gt;and that tool only runs on macOS&lt;/strong&gt;. So Windows users hit a dead end: Transporter has a Windows version, yet on Windows it insists that you provide a file that can only be generated on a Mac.&lt;/p&gt;

&lt;p&gt;The common workaround online is to find a Mac to generate it and copy it over, or rent a cloud Mac — spinning up an entire machine for a file of a few dozen KB is clearly not worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With the AppUploader command-line tool, you can generate this file directly on Windows&lt;/strong&gt;, with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;appuploader&lt;/span&gt;&lt;span class="na"&gt;-cli &lt;/span&gt;&lt;span class="kd"&gt;info&lt;/span&gt; &lt;span class="na"&gt;-u &lt;/span&gt;&lt;span class="kd"&gt;dev&lt;/span&gt;@example.com &lt;span class="kd"&gt;App&lt;/span&gt;.ipa &lt;span class="na"&gt;-o &lt;/span&gt;&lt;span class="kd"&gt;AppStoreInfo&lt;/span&gt;.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;appuploader-cli.exe&lt;/code&gt; is in the AppUploader install directory; it comes with the main program, so there's no separate download;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-u&lt;/code&gt; takes your Apple ID email;&lt;/li&gt;
&lt;li&gt;the trailing &lt;code&gt;-o&lt;/code&gt; specifies the output file name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it finishes, it prints a line with the file size and the package's Bundle ID, so you can check that you're uploading the package you intended:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plist"&gt;&lt;code&gt;&lt;span class="l"&gt;asset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;description&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;written&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;AppStoreInfo.plist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="l"&gt;93613&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;xml&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;plist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bundle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;com.example.app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Put the IPA and the plist in the same directory.&lt;/strong&gt; This is one of the more commonly hit pitfalls in practice: when the two files are scattered across different paths, the upload tends to fail. Keeping them together is the least hassle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3: Prepare account credentials
&lt;/h2&gt;

&lt;p&gt;iTMSTransporter supports two login methods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Apple ID + app-specific password.&lt;/strong&gt; Go to &lt;a href="https://account.apple.com/account/manage" rel="noopener noreferrer"&gt;https://account.apple.com/account/manage&lt;/a&gt; and generate an app-specific password in the form &lt;code&gt;abcd-efgh-ijkl-mnop&lt;/code&gt;. It is shown only once, so save it on the spot. Pass it with &lt;code&gt;-u&lt;/code&gt; and &lt;code&gt;-p&lt;/code&gt; on the command line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: App Store Connect API key (recommended).&lt;/strong&gt; Generate one at &lt;a href="https://appstoreconnect.apple.com/access/api" rel="noopener noreferrer"&gt;https://appstoreconnect.apple.com/access/api&lt;/a&gt;, and you get a key ID, an Issuer ID, and a &lt;code&gt;.p8&lt;/code&gt; file. iTMSTransporter is particular about where the &lt;code&gt;.p8&lt;/code&gt; lives: &lt;strong&gt;it does not accept a path you pass in&lt;/strong&gt;; instead it looks for a fixed file name in several fixed directories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./private_keys/AuthKey_&amp;lt;key ID&amp;gt;.p8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is, create a &lt;code&gt;private_keys&lt;/code&gt; folder in the current directory where you run the command, and put the file in it named &lt;code&gt;AuthKey_&amp;lt;key ID&amp;gt;.p8&lt;/code&gt;. Besides the current directory, it also looks in &lt;code&gt;~/private_keys&lt;/code&gt;, &lt;code&gt;~/.private_keys&lt;/code&gt;, and &lt;code&gt;~/.appstoreconnect/private_keys&lt;/code&gt;, in that order, and you can also specify a directory with the &lt;code&gt;API_PRIVATE_KEYS_DIR&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A side note: Transporter also has a &lt;code&gt;-jwt&lt;/code&gt; parameter that takes a token directly, but since late September 2025, &lt;code&gt;-jwt&lt;/code&gt; combined with &lt;code&gt;-assetDescription&lt;/code&gt; has had server-side rejection issues, reporting &lt;code&gt;No value present&lt;/code&gt;. &lt;strong&gt;The &lt;code&gt;-apiKey&lt;/code&gt; / &lt;code&gt;-apiIssuer&lt;/code&gt; pair does not have this problem&lt;/strong&gt;, so avoid &lt;code&gt;-jwt&lt;/code&gt; if you can.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4: Verify first, then upload
&lt;/h2&gt;

&lt;p&gt;Before the real upload, it is advisable to run a verification pass first; it catches problems with the package itself early and saves you from waiting through an upload only to be rejected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;iTMSTransporter&lt;/span&gt; &lt;span class="na"&gt;-m &lt;/span&gt;&lt;span class="nb"&gt;verify&lt;/span&gt; &lt;span class="na"&gt;-assetFile &lt;/span&gt;&lt;span class="kd"&gt;App&lt;/span&gt;.ipa &lt;span class="na"&gt;-assetDescription &lt;/span&gt;&lt;span class="kd"&gt;AppStoreInfo&lt;/span&gt;.plist &lt;span class="na"&gt;-u &lt;/span&gt;&lt;span class="kd"&gt;dev&lt;/span&gt;@example.com &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="kd"&gt;abcd&lt;/span&gt;&lt;span class="na"&gt;-efgh-ijkl-mnop
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once verification passes, upload by changing &lt;code&gt;-m verify&lt;/code&gt; to &lt;code&gt;-m upload&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;iTMSTransporter&lt;/span&gt; &lt;span class="na"&gt;-m &lt;/span&gt;&lt;span class="kd"&gt;upload&lt;/span&gt; &lt;span class="na"&gt;-assetFile &lt;/span&gt;&lt;span class="kd"&gt;App&lt;/span&gt;.ipa &lt;span class="na"&gt;-assetDescription &lt;/span&gt;&lt;span class="kd"&gt;AppStoreInfo&lt;/span&gt;.plist &lt;span class="na"&gt;-u &lt;/span&gt;&lt;span class="kd"&gt;dev&lt;/span&gt;@example.com &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="kd"&gt;abcd&lt;/span&gt;&lt;span class="na"&gt;-efgh-ijkl-mnop
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using an API key (remember to create the &lt;code&gt;private_keys&lt;/code&gt; directory first):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;iTMSTransporter&lt;/span&gt; &lt;span class="na"&gt;-m &lt;/span&gt;&lt;span class="kd"&gt;upload&lt;/span&gt; &lt;span class="na"&gt;-assetFile &lt;/span&gt;&lt;span class="kd"&gt;App&lt;/span&gt;.ipa &lt;span class="na"&gt;-assetDescription &lt;/span&gt;&lt;span class="kd"&gt;AppStoreInfo&lt;/span&gt;.plist &lt;span class="na"&gt;-apiKey &lt;/span&gt;&lt;span class="kd"&gt;UK29KBAX9X&lt;/span&gt; &lt;span class="na"&gt;-apiIssuer &lt;/span&gt;&lt;span class="m"&gt;69&lt;/span&gt;&lt;span class="kd"&gt;a6de78&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;4459&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;47&lt;/span&gt;&lt;span class="kd"&gt;e3&lt;/span&gt;&lt;span class="na"&gt;-e&lt;/span&gt;&lt;span class="m"&gt;053&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="kd"&gt;b8c7c11a4d1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parameter reference:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;-m upload&lt;/code&gt; / &lt;code&gt;-m verify&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Upload / verify only without uploading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-assetFile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Path to the IPA or PKG (&lt;strong&gt;stop using &lt;code&gt;-f&lt;/code&gt;&lt;/strong&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-assetDescription&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The AppStoreInfo.plist generated in the previous step; required on Windows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;-u&lt;/code&gt; / &lt;code&gt;-p&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Apple ID and app-specific password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;-apiKey&lt;/code&gt; / &lt;code&gt;-apiIssuer&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;API key ID and Issuer ID; mutually exclusive with &lt;code&gt;-u -p&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Log verbosity: &lt;code&gt;off&lt;/code&gt;, &lt;code&gt;critical&lt;/code&gt;, &lt;code&gt;informational&lt;/code&gt;, &lt;code&gt;detailed&lt;/code&gt;, &lt;code&gt;eXtreme&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When troubleshooting, add &lt;code&gt;-v eXtreme&lt;/code&gt; for much more detailed output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;iTMSTransporter&lt;/span&gt; &lt;span class="na"&gt;-m &lt;/span&gt;&lt;span class="kd"&gt;upload&lt;/span&gt; &lt;span class="na"&gt;-v &lt;/span&gt;&lt;span class="kd"&gt;eXtreme&lt;/span&gt; &lt;span class="na"&gt;-assetFile &lt;/span&gt;&lt;span class="kd"&gt;App&lt;/span&gt;.ipa &lt;span class="na"&gt;-assetDescription &lt;/span&gt;&lt;span class="kd"&gt;AppStoreInfo&lt;/span&gt;.plist &lt;span class="na"&gt;-apiKey &lt;/span&gt;&lt;span class="kd"&gt;UK29KBAX9X&lt;/span&gt; &lt;span class="na"&gt;-apiIssuer &lt;/span&gt;&lt;span class="m"&gt;69&lt;/span&gt;&lt;span class="kd"&gt;a6de78&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;4459&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;47&lt;/span&gt;&lt;span class="kd"&gt;e3&lt;/span&gt;&lt;span class="na"&gt;-e&lt;/span&gt;&lt;span class="m"&gt;053&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="kd"&gt;b8c7c11a4d1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the upload, Apple still needs a few minutes to a few tens of minutes to process it, and only then does the build appear in the "Builds" list in App Store Connect; only after that can you select it for review submission. Not seeing it right after uploading is normal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common errors
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Says &lt;code&gt;-f&lt;/code&gt; cannot be used to upload apps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Old syntax. Switch to &lt;code&gt;-assetFile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Says the asset description is missing, or fails with no message at all&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On Windows, &lt;code&gt;-assetDescription&lt;/code&gt; is required; check whether you left it out and whether the path is correct. Also make sure the IPA and the plist are in the same directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reports &lt;code&gt;No value present&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A known issue when passing a token via &lt;code&gt;-jwt&lt;/code&gt;; switch to the &lt;code&gt;-apiKey&lt;/code&gt; / &lt;code&gt;-apiIssuer&lt;/code&gt; pair.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API key authentication fails, saying the key can't be found&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.p8&lt;/code&gt; location or file name is wrong. It must be &lt;code&gt;private_keys/AuthKey_&amp;lt;key ID&amp;gt;.p8&lt;/code&gt;, placed in the current directory where you run the command, and the key ID in the file name must match the &lt;code&gt;-apiKey&lt;/code&gt; parameter exactly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Duplicate version number or build number&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That version number + build number combination has already been uploaded; Apple does not allow overwriting, so change the build number and repackage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Java-related errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Transporter bundles its own runtime, so you generally do not need to install Java separately. If you get a Java-related error, it is usually an incomplete installation — uninstall and reinstall.&lt;/p&gt;

&lt;h2&gt;
  
  
  By the way: you don't actually have to go through all this
&lt;/h2&gt;

&lt;p&gt;The whole process above — installing Transporter, generating the plist, setting up the &lt;code&gt;private_keys&lt;/code&gt; directory, assembling a long string of parameters — if your only goal is "get the IPA uploaded," there is a shorter path: the same &lt;code&gt;appuploader-cli&lt;/code&gt; you used to generate the plist can upload directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;appuploader&lt;/span&gt;&lt;span class="na"&gt;-cli &lt;/span&gt;&lt;span class="kd"&gt;upload&lt;/span&gt; &lt;span class="na"&gt;-f &lt;/span&gt;&lt;span class="kd"&gt;App&lt;/span&gt;.ipa &lt;span class="na"&gt;-u &lt;/span&gt;&lt;span class="kd"&gt;dev&lt;/span&gt;@example.com &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="kd"&gt;abcd&lt;/span&gt;&lt;span class="na"&gt;-efgh-ijkl-mnop
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command does the upload; no AppStoreInfo.plist needed, no Transporter install needed, and on failure the exit code is non-zero, so you can wire it straight into your build script.&lt;/p&gt;

&lt;p&gt;When is it still worth using iTMSTransporter: when company process explicitly requires Apple's official tools, or when your pipeline already has other stages built around Transporter. In those two cases, just use &lt;code&gt;appuploader-cli info&lt;/code&gt; to fill in the AppStoreInfo.plist piece and keep the rest as is.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Apple's official Transporter User Guide: &lt;a href="https://help.apple.com/itc/transporteruserguide/" rel="noopener noreferrer"&gt;https://help.apple.com/itc/transporteruserguide/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The most troublesome part of the whole setup is really the AppStoreInfo.plist step; the rest is just filling in parameters. The plist is generated with the command-line tool bundled with AppUploader, which on Windows can also sign certificates, create Bundle IDs, and generate provisioning profiles.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
    </item>
    <item>
      <title>Must-Have Programming Tools for iOS Developers: Five Categories, Compared and How to Choose</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Mon, 21 Sep 2026 10:57:56 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/must-have-programming-tools-for-ios-developers-five-categories-compared-and-how-to-choose-439a</link>
      <guid>https://dev.to/uikit_ninja/must-have-programming-tools-for-ios-developers-five-categories-compared-and-how-to-choose-439a</guid>
      <description>&lt;p&gt;I've noticed a pattern: every time a new person joins an iOS team, their first question is almost never about syntax — it's "what else do I need to install besides Xcode?" The answer is a long one, because the programming tools involved in iOS development go far beyond a single IDE. By purpose, they fall into five categories, and each category offers different choices. This article catalogs the must-have programming tools for iOS developers by category, presents representative tools and selection thinking for each, and helps you set up your development environment in one go.&lt;/p&gt;

&lt;h2&gt;
  
  
  IDEs and Editors
&lt;/h2&gt;

&lt;p&gt;The first category is IDEs and editors — the main battleground for writing code. Xcode is the official all-in-one bundle: compilation, debugging, simulator, and App Store submission all in one. Its downsides are its large size and frequent updates; when disk space is tight or the network is poor, a single install is quite a chore. If you don't want to be tied to Xcode, &lt;strong&gt;KXApp&lt;/strong&gt; (Kuai Xie) is another route: it ships with a built-in compilation toolchain, so you can do iOS development without installing or updating Xcode. It supports Swift, Objective-C, and Flutter projects, and once you connect an iPhone it builds and installs to a real device in one click, eliminating the export-IPA-then-drag-into-Xcode workflow. VS Code, meanwhile, represents the lightweight camp, with a rich plugin ecosystem, suiting developers who like to customize their editor. Each of the three has its own use cases — just pick according to your team's habits.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Coding Assistants
&lt;/h2&gt;

&lt;p&gt;The second category is AI coding assistants. GitHub Copilot is mature in code completion and generation, while &lt;strong&gt;Cursor&lt;/strong&gt; integrates AI capabilities into the editor experience. &lt;strong&gt;KXApp&lt;/strong&gt; is built on the VS Code kernel, so it can directly use various AI code assistant plugins; combined with a standardized project structure and intelligent suggestions, it gives you a familiar editing experience from the very first line of code. If your editor itself supports a plugin ecosystem, adding an AI assistant is a natural extension with no extra learning curve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build and Release
&lt;/h2&gt;

&lt;p&gt;The third category is build and release tools. &lt;strong&gt;xcodebuild&lt;/strong&gt; is the standard way to build from the command line, and paired with fastlane it can form a pipeline for automatic signing and automatic uploads — ideal for teams that release frequently. If your project is small and your process is simple, &lt;strong&gt;KXApp&lt;/strong&gt;'s one-click build can generate an installation package directly, covering test distribution and App Store submission scenarios, and skipping the step of configuring scripts. The trade-off between the two approaches depends on team size: the more complex the process, the more scripts are worth it; otherwise, the tool's built-in one-click capability is faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging and Performance Analysis
&lt;/h2&gt;

&lt;p&gt;The fourth category is debugging and performance tools. LLDB breakpoint debugging is the foundation of iOS debugging, while Instruments handles performance analysis, with templates for CPU, memory, and leaks. Real-device verification is a key step for functional correctness; &lt;strong&gt;KXApp&lt;/strong&gt; has a built-in live real-device debugging engine — connect an iPhone and it runs, with code changes synced quickly to the phone for WYSIWYG results, without going through a full build first. Do functional verification and performance analysis separately, each with the tool that suits it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Management
&lt;/h2&gt;

&lt;p&gt;The fifth category is code management tools. Git is the foundation; whether you use the command line or a GUI client is a matter of personal habit. SourceTree and GitHub Desktop are friendly for visual operations and suit developers who don't want to memorize commands. Choices in this category barely affect the other four — convenience matters most.&lt;/p&gt;

&lt;p&gt;With the categories covered, when it comes down to individuals, the configuration for newcomers and veterans differs quite a bit. Newcomers should start with a complete IDE — pick either &lt;strong&gt;Xcode&lt;/strong&gt; or &lt;strong&gt;KXApp&lt;/strong&gt; — and get the project running first. It's worth hooking up an AI assistant early, since it saves a lot of time digging through documentation. Veterans, by contrast, tend to slim down their toolchain: for example, running xcodebuild and fastlane only on CI machines, keeping just an editor and a handy branch management tool locally. There's no standard answer for environment setup — satisfying your current stage's needs is enough. Tools change with the project, and that judgment itself matters more than which one you pick.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
      <category>development</category>
      <category>flutter</category>
    </item>
    <item>
      <title>Packet Eagle: Port Scan &amp; Subdomain Discovery for Asset Inventory</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Sun, 20 Sep 2026 11:49:03 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/packet-eagle-port-scan-subdomain-discovery-for-asset-inventory-57jj</link>
      <guid>https://dev.to/uikit_ninja/packet-eagle-port-scan-subdomain-discovery-for-asset-inventory-57jj</guid>
      <description>&lt;h1&gt;
  
  
  Port Scanning and Subdomain Discovery
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;You have a host or a domain name and want to know what it exposes to the outside? Each approach has its own use: &lt;strong&gt;port scanning&lt;/strong&gt; actively probes which ports a host has open and what services run on them; &lt;strong&gt;subdomain discovery&lt;/strong&gt; reads only public data, never interacts with the target, and still digs out the subdomains under a domain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. Port Scanning: Which Ports a Host Has Open and What Services Run on Them
&lt;/h2&gt;

&lt;p&gt;Enter a hostname or IP and it quickly scans out its open &lt;strong&gt;TCP ports&lt;/strong&gt;, showing progress and "N open found" in real time. Each open port has three columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Port number.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service name&lt;/strong&gt;: first guessed from the port, then &lt;strong&gt;corrected against the captured Banner&lt;/strong&gt; — so even if SSH, redis, mysql and the like run on non-standard ports, they are still recognized.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Banner&lt;/strong&gt;: the captured service greeting; for HTTP ports, the status line and &lt;code&gt;Server&lt;/code&gt; header.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scan range&lt;/strong&gt; has three choices: &lt;strong&gt;common ports&lt;/strong&gt; (the default, a curated set of high-frequency ports), &lt;strong&gt;all ports (1–65535)&lt;/strong&gt;, or &lt;strong&gt;custom&lt;/strong&gt; (e.g. &lt;code&gt;80,443,8000-8100&lt;/code&gt;). Banner grabbing can be toggled — with it off, the service name is still derived from the port, but no greeting is captured and no correction is made from it. The open-port list can be sorted by port number. &lt;strong&gt;Works out of the box&lt;/strong&gt;, no extra drivers or privileges required.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Non-standard ports are still recognized&lt;/strong&gt;: run SSH, redis, mysql and the like on an obscure port and an ordinary scanner that only "guesses the service from the port number" gets it wrong — here the captured Banner is used for correction, so the real service is identified no matter which port it runs on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Subdomain Discovery: Passively Map Out a Domain's Subdomains
&lt;/h2&gt;

&lt;p&gt;Enter a domain name and it aggregates several &lt;strong&gt;public intelligence sources&lt;/strong&gt; queried in parallel, listing the subdomains under it. Sources are shown in two categories (each with a hit count): &lt;strong&gt;certificate transparency logs&lt;/strong&gt; and &lt;strong&gt;passive DNS&lt;/strong&gt;. Results are automatically &lt;strong&gt;deduplicated and sorted&lt;/strong&gt;, with real-time filtering and one-click &lt;strong&gt;copy all&lt;/strong&gt;. If a source is temporarily unavailable or rate-limited, it won't drag down the whole run — the remaining sources still return results, each annotated with its hit count.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reads only public data, never interacts with the target&lt;/strong&gt;: throughout, it only queries public datasets and &lt;strong&gt;sends no requests to the target domain or its servers&lt;/strong&gt;. This is the fundamental difference from "active scanning".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Active vs. Passive: How They Work Together
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Port scanning&lt;/th&gt;
&lt;th&gt;Subdomain discovery&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Target&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A host / IP&lt;/td&gt;
&lt;td&gt;A domain name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Method&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Actively&lt;/strong&gt; probe the target's ports&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Passively&lt;/strong&gt; query public intelligence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interacts with target&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (connects directly to its ports)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No&lt;/strong&gt; (reads only public data)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What you get&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open ports + services + Banners&lt;/td&gt;
&lt;td&gt;A list of externally exposed subdomains&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;First use &lt;strong&gt;subdomain discovery&lt;/strong&gt; to read public data and spread out a domain's asset surface, then use &lt;strong&gt;port scanning&lt;/strong&gt; on the hosts you pick out to verify which services are open — passive mapping of the surface, active verification of the points; run the pair and your external exposure becomes clear.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. When to Use It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To map out the &lt;strong&gt;service surface&lt;/strong&gt; a device / server exposes: which ports are open, roughly what runs on them, and what the Banner says.&lt;/li&gt;
&lt;li&gt;To have a domain name and want to &lt;strong&gt;inventory the subdomains it exposes&lt;/strong&gt; using public data alone.&lt;/li&gt;
&lt;li&gt;For asset inventory and sorting out external exposure: passively mine subdomains + actively verify ports, the two complementing each other.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mobile</category>
      <category>software</category>
      <category>networking</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>appuploader-cli Tutorial: Uploading an IPA to the App Store from the Command Line on Windows</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Wed, 16 Sep 2026 10:15:52 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/appuploader-cli-tutorial-uploading-an-ipa-to-the-app-store-from-the-command-line-on-windows-pco</link>
      <guid>https://dev.to/uikit_ninja/appuploader-cli-tutorial-uploading-an-ipa-to-the-app-store-from-the-command-line-on-windows-pco</guid>
      <description>&lt;h1&gt;
  
  
  appuploader-cli Tutorial: Uploading an IPA to the App Store from the Command Line on Windows
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;One command pushes your built IPA to App Store Connect — no Mac, no Xcode:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appuploader-cli upload &lt;span class="nt"&gt;-f&lt;/span&gt; Payload.ipa &lt;span class="nt"&gt;-u&lt;/span&gt; dev@example.com &lt;span class="nt"&gt;-p&lt;/span&gt; abcd-efgh-ijkl-mnop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;appuploader-cli&lt;/code&gt; is the command-line tool bundled with AppUploader (开心上架); once the app is installed, it's right there in the install directory. Below is a walkthrough from scratch: how to find it, what you need before your first upload, which login method to use for teams and pipelines, and how to diagnose failed uploads.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you need the command line
&lt;/h2&gt;

&lt;p&gt;If a couple of clicks in the GUI can submit your build, most people don't need the CLI. It's really for these three situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The build is produced automatically.&lt;/strong&gt; CI packages a build every time you commit, and then someone still has to click upload manually — that step should be wired in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The upload has to be run by someone else.&lt;/strong&gt; Outsourcing, agency work, releasing multiple apps in rotation — a script beats verbally explaining which button to click.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On a machine with no GUI.&lt;/strong&gt; Such as a company build server with only a remote terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you only publish manually once in a while, clicking twice in the GUI is actually faster; the value of the CLI is in repeated execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you start
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. You need a signed package first.&lt;/strong&gt; &lt;code&gt;appuploader-cli&lt;/code&gt; handles the "hand the package to Apple" step; it does not compile or sign. You must already have a built &lt;code&gt;.ipa&lt;/code&gt; (iOS) or &lt;code&gt;.pkg&lt;/code&gt; (macOS).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Find the command.&lt;/strong&gt; Once AppUploader is installed, it's already in the install directory:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;appuploader-cli.exe&lt;/code&gt; in the same directory as the main program &lt;code&gt;AppUploader.exe&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AppUploader.app/Contents/Resources/appuploader-cli&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Open a terminal in that directory and you can use it directly. If you don't want to &lt;code&gt;cd&lt;/code&gt; there every time, add the directory to your system &lt;code&gt;PATH&lt;/code&gt; (on Windows: Settings → System → About → Advanced system settings → Environment Variables → select Path → Edit → New, paste the directory path, then &lt;strong&gt;reopen a terminal&lt;/strong&gt; for it to take effect).&lt;/p&gt;

&lt;p&gt;Run one command to confirm it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appuploader-cli &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it lists &lt;code&gt;upload&lt;/code&gt; and &lt;code&gt;info&lt;/code&gt;, you've found the right one.&lt;/p&gt;

&lt;h2&gt;
  
  
  First upload: using an app-specific password
&lt;/h2&gt;

&lt;p&gt;The most convenient credential for logging in to Apple from the command line is an &lt;strong&gt;app-specific password&lt;/strong&gt; — Apple created these specifically for third-party tools, they &lt;strong&gt;do not trigger two-factor authentication&lt;/strong&gt;, and you don't have to confirm on your phone for every upload.&lt;/p&gt;

&lt;p&gt;Generate one first: sign in at &lt;a href="https://account.apple.com/account/manage" rel="noopener noreferrer"&gt;https://account.apple.com/account/manage&lt;/a&gt;, find "App-Specific Passwords," and create a new one. You'll get a password shaped like &lt;code&gt;abcd-efgh-ijkl-mnop&lt;/code&gt;, &lt;strong&gt;shown only once&lt;/strong&gt;, so copy and save it right away.&lt;/p&gt;

&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appuploader-cli upload &lt;span class="nt"&gt;-f&lt;/span&gt; Payload.ipa &lt;span class="nt"&gt;-u&lt;/span&gt; dev@example.com &lt;span class="nt"&gt;-p&lt;/span&gt; abcd-efgh-ijkl-mnop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three arguments: &lt;code&gt;-f&lt;/code&gt; is the path to the package (you can also omit &lt;code&gt;-f&lt;/code&gt; and put the path at the end of the command), &lt;code&gt;-u&lt;/code&gt; is the Apple ID email, and &lt;code&gt;-p&lt;/code&gt; is the app-specific password you just created.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure &lt;code&gt;-p&lt;/code&gt; is the &lt;strong&gt;app-specific password&lt;/strong&gt;, not the password you normally use to sign in to your Apple ID. An app-specific password is always 16 letters with three hyphens in the middle, looks nothing like your login password, and you can tell at a glance whether you got it wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After you press Enter, progress prints line by line, and a few minutes later you'll see this line, meaning success:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; upload finished successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On failure it's &lt;code&gt;&amp;gt; upload finished with error:&lt;/code&gt;, followed directly by the reason Apple gave — a duplicate version number, a signature mismatch, a missing Info.plist field, and so on; just fix accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In scripts you don't need to read the logs: on failure the command's exit code is non-zero, so checking the exit code is enough.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't rush to App Store Connect to look for the build right after uploading — Apple takes anywhere from a few minutes to a few tens of minutes to process the package, and only after that does it appear in the "Builds" list, at which point you can select it for review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uploading macOS / tvOS / visionOS packages
&lt;/h3&gt;

&lt;p&gt;It's treated as iOS by default; add &lt;code&gt;--type&lt;/code&gt; for other platforms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appuploader-cli upload &lt;span class="nt"&gt;-u&lt;/span&gt; dev@example.com &lt;span class="nt"&gt;-p&lt;/span&gt; abcd-efgh-ijkl-mnop &lt;span class="nt"&gt;--type&lt;/span&gt; osx App.pkg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are only four possible values: &lt;code&gt;ios&lt;/code&gt; (default), &lt;code&gt;osx&lt;/code&gt;, &lt;code&gt;appletvos&lt;/code&gt;, &lt;code&gt;xros&lt;/code&gt; (visionOS).&lt;/p&gt;

&lt;h2&gt;
  
  
  Teams and CI: switch to API key login
&lt;/h2&gt;

&lt;p&gt;The approach in the previous section has a problem: the command carries an individual's Apple ID and password. If that person leaves, changes their password, or simply doesn't want to hand their account to the pipeline, the whole automation breaks.&lt;/p&gt;

&lt;p&gt;For team scenarios, an &lt;strong&gt;App Store Connect API key&lt;/strong&gt; is more appropriate: it belongs to the team rather than an individual, can be revoked independently, and doesn't involve two-factor authentication.&lt;/p&gt;

&lt;p&gt;Generate one at &lt;a href="https://appstoreconnect.apple.com/access/api" rel="noopener noreferrer"&gt;https://appstoreconnect.apple.com/access/api&lt;/a&gt; (requires Account Holder or Admin permission) and you'll get three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key ID&lt;/strong&gt; (a string of uppercase letters and digits)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Issuer ID&lt;/strong&gt; (at the top of the page, shaped like &lt;code&gt;69a6de78-4459-47e3-e053-5b8c7c11a4d1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;.p8&lt;/code&gt; private key file&lt;/strong&gt; — &lt;strong&gt;downloadable only once&lt;/strong&gt;, Apple gives no second chance, so save it immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then replace &lt;code&gt;-u -p&lt;/code&gt; with these three arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appuploader-cli upload &lt;span class="nt"&gt;-f&lt;/span&gt; Payload.ipa &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--api-key&lt;/span&gt; UK29KBAX9X &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--api-issuer&lt;/span&gt; 69a6de78-4459-47e3-e053-5b8c7c11a4d1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--private-key&lt;/span&gt; AuthKey_UK29KBAX9X.p8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two login methods are &lt;strong&gt;mutually exclusive&lt;/strong&gt;; mixing them is rejected outright.&lt;/p&gt;

&lt;p&gt;Confirm two things before using an API key:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You can only upload &lt;code&gt;.ipa&lt;/code&gt;.&lt;/strong&gt; This method relies on the Bundle ID in the package to find the corresponding app on App Store Connect, which can't be obtained from a &lt;code&gt;.pkg&lt;/code&gt;. For macOS packages, stick with the app-specific password from the previous section.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An app must already exist in App Store Connect for this Bundle ID.&lt;/strong&gt; If not, you'll get &lt;code&gt;no App Store Connect app found for bundle ID&lt;/code&gt; — create the app first, then upload.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wiring it into a pipeline
&lt;/h2&gt;

&lt;p&gt;The idea is one sentence: after the build produces the IPA, add an &lt;code&gt;upload&lt;/code&gt; step, and pass credentials via the CI's built-in secrets rather than writing them in plaintext in the script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Actions&lt;/strong&gt; (store the three items as repository secrets):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload to App Store Connect&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ASC_KEY_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;${{ secrets.ASC_KEY_ID }}&lt;/span&gt;
    &lt;span class="na"&gt;ASC_ISSUER_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ASC_ISSUER_ID }}&lt;/span&gt;
    &lt;span class="na"&gt;ASC_P8&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;${{ secrets.ASC_P8 }}&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;printf '%s' "$ASC_P8" &amp;gt; AuthKey.p8&lt;/span&gt;
    &lt;span class="s"&gt;appuploader-cli upload -f build/App.ipa \&lt;/span&gt;
      &lt;span class="s"&gt;--api-key "$ASC_KEY_ID" \&lt;/span&gt;
      &lt;span class="s"&gt;--api-issuer "$ASC_ISSUER_ID" \&lt;/span&gt;
      &lt;span class="s"&gt;--private-key AuthKey.p8&lt;/span&gt;
    &lt;span class="s"&gt;rm -f AuthKey.p8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't skip that last &lt;code&gt;rm&lt;/code&gt; line — the private key shouldn't be left in the Runner's working directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jenkins / generic shell&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;   &lt;span class="c"&gt;# abort the whole pipeline if the upload fails&lt;/span&gt;
appuploader-cli upload &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKSPACE&lt;/span&gt;&lt;span class="s2"&gt;/build/App.ipa"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$APPLE_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$APP_SPECIFIC_PASSWORD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows batch / PowerShell&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\Program Files\AppUploader\appuploader-cli.exe"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;upload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\build\App.ipa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;APPLE_ID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;APP_PASSWORD&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$LASTEXITCODE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-ne&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;throw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Upload failed"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole process needs no Mac; even if the build machine is Windows, this step still runs fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  By the way: inspecting a package without uploading
&lt;/h2&gt;

&lt;p&gt;There's also the &lt;code&gt;info&lt;/code&gt; command, which doesn't upload over the network — it only reads the package locally and generates the resource description file App Store needs, &lt;code&gt;AppStoreInfo.plist&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appuploader-cli info &lt;span class="nt"&gt;-u&lt;/span&gt; dev@example.com Payload.ipa &lt;span class="nt"&gt;-o&lt;/span&gt; AppStoreInfo.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two uses: confirm the package itself is fine before uploading (on success it prints the package's Bundle ID and size, so you can double-check you're uploading the right one); or your process uses a different upload tool and you're only missing this plist.&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;-o&lt;/code&gt; it prints to the terminal, which is handy for piping. &lt;code&gt;info&lt;/code&gt; only supports the &lt;code&gt;-u&lt;/code&gt; account form, with no API key mode.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
    </item>
    <item>
      <title>Understanding the iOS Development Toolchain: A Comprehensive Comparison and Selection Guide for Cursor, Xcode, and KXApp</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Tue, 15 Sep 2026 10:11:12 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/understanding-the-ios-development-toolchain-a-comprehensive-comparison-and-selection-guide-for-28db</link>
      <guid>https://dev.to/uikit_ninja/understanding-the-ios-development-toolchain-a-comprehensive-comparison-and-selection-guide-for-28db</guid>
      <description>&lt;p&gt;I've noticed a trend: there are more and more tools to choose from for iOS development today. Besides Apple's official Xcode, there's the AI-driven Cursor and the lightweight KXApp. Many teams and indie developers hesitate among the three when picking an IDE. This iOS development toolchain comparison puts all three side by side, comparing them across the core dimensions of compilation, debugging, AI capabilities, and learning cost, so you can choose based on your own situation. Once you understand where each tool fits in the iOS development toolchain, the decision won't feel so agonizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Xcode: The Most Feature-Complete Official IDE
&lt;/h2&gt;

&lt;p&gt;Xcode is Apple's official iOS development IDE, covering the entire workflow of coding, debugging, performance profiling, and packaging for release. Its strength is tight integration: performance analysis with Instruments, crash logs with Organizer, and UI building with Interface Builder all live in the same toolset. It suits teams doing pure native Swift or OC development that need deep debugging. The downside is an installer of over ten gigabytes, and every major version update means another full download, which places high demands on disk and memory. In cross-platform projects (Flutter, uni-app), many features go unused, yet the disk footprint doesn't shrink at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cursor: An AI-Assisted Editor
&lt;/h2&gt;

&lt;p&gt;Cursor is an AI-driven editor built on VS Code. Its core advantage is built-in code completion and conversational programming: when writing Swift code, you can describe your requirements in natural language and let the AI generate or complete the code. It's good for rapid prototyping and learning Swift syntax. But Cursor is not a complete iOS IDE by itself — it doesn't support compilation, signing, running on a real device, or packaging. To write an iOS app, you still need Xcode or command-line tools to handle building and debugging. If Xcode is already your primary tool, you can use Cursor to help write code and then compile and run in Xcode. If you don't want to install Xcode, consider a tool like KXApp that ships with its own compilation chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  KXApp: A Lightweight iOS IDE
&lt;/h2&gt;

&lt;p&gt;KXApp positions itself as a lightweight iOS development IDE. It requires no installation of Xcode or Command Line Tools and has a complete compilation toolchain built in. When creating a project, choose Swift, OC, or Flutter, and a standardized structure is generated in one click. The coding interface is based on VS Code, with intelligent completion and an AI assistant available by default. Real-device debugging saves a lot of steps — connect your iPhone to the computer, click Build and Install, and it compiles, signs, and installs onto the phone directly, with no need to configure certificates yourself. Flutter projects are supported too: cross-platform developers can manage both the native layer and the Flutter layer code in the same IDE, without opening Xcode separately just to work on the iOS part. When the project is done, build an IPA in one click for test distribution or release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Comparisons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Compilation capability:&lt;/strong&gt; Only Xcode and KXApp have an integrated compilation toolchain; Cursor needs external tooling. &lt;strong&gt;Real-device debugging:&lt;/strong&gt; Xcode and KXApp support one-click runs on a real device; Cursor can't do it directly. &lt;strong&gt;AI capability:&lt;/strong&gt; Cursor's AI is relatively the strongest; KXApp also has basic AI completion; Xcode's AI features are limited. &lt;strong&gt;Learning cost:&lt;/strong&gt; KXApp is the lowest, Xcode the highest, and Cursor sits in between. &lt;strong&gt;Cross-platform support:&lt;/strong&gt; Both KXApp and Cursor can handle Flutter projects; Xcode leans native.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Choose
&lt;/h2&gt;

&lt;p&gt;Choose Xcode if your main work is native development and you need Instruments for performance profiling. Choose Cursor if you're after AI-assisted coding but can accept using other tools to complete the build. Choose KXApp if you want a lightweight environment, a quick start, cross-platform development, or simply don't want to burn too much energy on toolchain configuration. There's no absolute right or wrong among the three iOS development toolchain options — tools serve the project, so pick according to your actual needs.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
      <category>development</category>
      <category>flutter</category>
    </item>
    <item>
      <title>HTTPS Capture Meets Certificate Pinning: Bypass App Certificate Validation with TraceEagle</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Tue, 15 Sep 2026 09:52:18 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/https-capture-meets-certificate-pinning-bypass-app-certificate-validation-with-traceeagle-1252</link>
      <guid>https://dev.to/uikit_ninja/https-capture-meets-certificate-pinning-bypass-app-certificate-validation-with-traceeagle-1252</guid>
      <description>&lt;h1&gt;
  
  
  Removing Certificate Pinning (Unpinning)
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Some apps use &lt;strong&gt;certificate pinning&lt;/strong&gt;: the certificate is installed and the proxy is running, yet the app stubbornly trusts only the certificate bundled inside it, and the moment it sees the proxy certificate it &lt;strong&gt;throws an error and refuses to connect&lt;/strong&gt;. This article shows you how to select such an app and &lt;strong&gt;remove its certificate validation with one click&lt;/strong&gt;, so that it trusts the proxy certificate again and HTTPS traffic can be decrypted normally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. When to Use This Capture Approach
&lt;/h2&gt;

&lt;p&gt;Come to this step when any of the following happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The certificate has been installed as described in Certificate Installation and the proxy is configured correctly, but &lt;strong&gt;a particular app simply can't get online / keeps reporting network errors&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Every other app works fine, and &lt;strong&gt;only this one&lt;/strong&gt; loses connectivity once the proxy is enabled — most likely because it uses certificate pinning.&lt;/li&gt;
&lt;li&gt;You want to capture this app, but it doesn't trust the proxy certificate, the handshake is cut short, and you can't even see the ciphertext in the request list.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The key distinction in one sentence&lt;/strong&gt;: removing certificate pinning only makes the app &lt;strong&gt;willing to trust the proxy certificate&lt;/strong&gt;; it doesn't perform decryption itself — the proxy still does that. If what you want is to &lt;strong&gt;pull plaintext directly out of the program's internals&lt;/strong&gt;, that's a different matter — see Application-Layer Capture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The proxy certificate is already installed and trusted — if not, see Certificate Installation first.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;proxy session&lt;/strong&gt; is already running: unpinning builds on proxy capture, so get other apps captured first, then deal with this stubborn one. See Proxy Capture.&lt;/li&gt;
&lt;li&gt;Prepare the corresponding environment for your target:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Desktop programs&lt;/strong&gt;: they can be listed and selected directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iOS apps&lt;/strong&gt;: the device is ready and the app is of a re-signable type; if you're unsure how to connect a device, see iOS Capture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Android apps&lt;/strong&gt;: the device is rooted; for connecting the device and capturing, see Android Capture.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Step-by-Step
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the "Remove Certificate Pinning (Unpin)" panel and switch to the tab matching your target: &lt;strong&gt;Desktop Programs / iOS Apps / Android Apps&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select the target to process:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Desktop programs&lt;/strong&gt;: check them in the process list; you can &lt;strong&gt;filter by process name or PID&lt;/strong&gt;, and multi-select is supported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iOS apps&lt;/strong&gt;: pick the device first, then choose from the app list; you can also &lt;strong&gt;enter the bundle ID manually&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Android apps&lt;/strong&gt;: pick the device first, then choose from the app list; you can also &lt;strong&gt;enter the package name / process name / PID manually&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Toggle the two switches as needed:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatically handle child processes&lt;/strong&gt; (desktop): in some applications, child processes are the ones sending and receiving network requests; enable this to handle them too and avoid missing traffic. It's recommended to keep it on for multi-process desktop apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restart target&lt;/strong&gt;: restart the app once before processing, so that requests sent &lt;strong&gt;during its early startup&lt;/strong&gt; are covered as well. Check this if you want to capture the few requests fired "the moment it opens".&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click Start. The panel gives &lt;strong&gt;real-time feedback on the result&lt;/strong&gt;: on success it tells you how many targets / processes were handled; if the app uses an uncommon networking component and isn't supported yet, it &lt;strong&gt;explicitly tells you&lt;/strong&gt; instead of leaving you waiting.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  4. Verification: Confirming It Now Yields Plaintext
&lt;/h2&gt;

&lt;p&gt;Once processing is done, go back to the proxy session and have the app send a request again (refresh the page, re-enter a feature):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The app that used to error out / lose connectivity now works normally&lt;/strong&gt;: it no longer fails to connect as soon as the proxy is on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Its traffic now appears in the request list&lt;/strong&gt;: request line, request headers, and body are all there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS shows "Decrypted"&lt;/strong&gt;: the response is readable plaintext (such as JSON), instead of the state where the handshake was cut short and nothing could be seen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the traffic shows up but the content is still ciphertext (not a rejected handshake, but something that can't be decrypted), that's usually not a certificate pinning problem; get the plaintext from inside the program instead — see Application-Layer Capture.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Can't Process It / Still Can't Connect? Check Item by Item
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Most likely cause&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The panel says this app isn't supported yet&lt;/td&gt;
&lt;td&gt;It uses an uncommon networking component&lt;/td&gt;
&lt;td&gt;Try a different approach and get plaintext from inside the program: switch to Application-Layer Capture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Processing succeeds, but only requests made after startup are captured; the first few are missed&lt;/td&gt;
&lt;td&gt;The app had already been running for a while when you processed it&lt;/td&gt;
&lt;td&gt;Check &lt;strong&gt;Restart target&lt;/strong&gt; and process again to cover requests from early startup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A desktop app has been processed, but some traffic is still missing&lt;/td&gt;
&lt;td&gt;Its network requests are sent by child processes&lt;/td&gt;
&lt;td&gt;Turn on &lt;strong&gt;Automatically handle child processes&lt;/strong&gt; and process again&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unpinning doesn't work for Go / Rust programs or desktop Java programs&lt;/td&gt;
&lt;td&gt;Such programs usually don't need unpinning&lt;/td&gt;
&lt;td&gt;They mostly read the system certificate store — just install the certificate into the system trust store; see Certificate Installation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS apps won't list / can't be selected&lt;/td&gt;
&lt;td&gt;The device isn't connected properly, or the app isn't of a re-signable type&lt;/td&gt;
&lt;td&gt;Prepare the device and environment as described in iOS Capture, or enter the bundle ID manually&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android apps won't list&lt;/td&gt;
&lt;td&gt;The device isn't rooted&lt;/td&gt;
&lt;td&gt;Prepare a rooted device as described in Android Capture&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Now that decryption works, how to read these requests, switch views, and decode them: see Viewing and Decoding Data.&lt;/li&gt;
&lt;li&gt;The full workflow for capturing a specific app on iOS / Android: see iOS Capture and Android Capture.&lt;/li&gt;
&lt;li&gt;To get plaintext directly from inside the program (bypassing the certificate route): see Application-Layer Capture.&lt;/li&gt;
&lt;li&gt;For private / in-house protocols that you want the tool to recognize: see Custom Protocol Decoding.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mobile</category>
      <category>software</category>
      <category>networking</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Guide to Applying for an iOS Push Certificate and Configuring APNs Bulk Push</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Mon, 14 Sep 2026 10:31:47 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/guide-to-applying-for-an-ios-push-certificate-and-configuring-apns-bulk-push-hnm</link>
      <guid>https://dev.to/uikit_ninja/guide-to-applying-for-an-ios-push-certificate-and-configuring-apns-bulk-push-hnm</guid>
      <description>&lt;h1&gt;
  
  
  Guide to Applying for an iOS Push Certificate and Configuring APNs Bulk Push
&lt;/h1&gt;

&lt;p&gt;To add push messaging to an iOS app, you first need an APNs push certificate, and then a push channel that can manage device tokens and support bulk sending — in &lt;strong&gt;AppUploader&lt;/strong&gt;, this entire set is an operations push platform independent of App Store Connect, with four tabs: Push Channels, Device Library, Send, and History.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Issue an APNs Push Certificate
&lt;/h2&gt;

&lt;p&gt;Open the "Certificates" page:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click "New Certificate" and select the push certificate type.&lt;/li&gt;
&lt;li&gt;Select the Bundle ID to bind (if you don't have one yet, register it on the "Bundle ID" page first).&lt;/li&gt;
&lt;li&gt;Fill in the certificate name and email, and set a &lt;code&gt;.p12&lt;/code&gt; protection password (the server does not store it, so keep it safe).&lt;/li&gt;
&lt;li&gt;We recommend enabling "Cloud Backup", so that you can use it directly on the push page later without transferring files back and forth.&lt;/li&gt;
&lt;li&gt;After submission, the push certificate is issued.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;A push certificate is deployed on the push server and used exclusively for the APNs channel; it is not used to sign and compile the app itself, which is where it differs from a signing certificate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 2: Create a Push Channel and Get the App Key
&lt;/h2&gt;

&lt;p&gt;Open the "Push Channels" tab on the "Push" page:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click "New Channel".&lt;/li&gt;
&lt;li&gt;Select the APNs push certificate issued in the previous step.&lt;/li&gt;
&lt;li&gt;Enter the export password of the certificate's &lt;code&gt;.p12&lt;/code&gt; (if the certificate has already been backed up to the cloud, entering the password is enough to retrieve the private key).&lt;/li&gt;
&lt;li&gt;Fill in the channel name (for example, "Marketing Push") and select the environment (Production / Sandbox — Sandbox is usually used during development and debugging).&lt;/li&gt;
&lt;li&gt;After submission the channel is created and you get an &lt;strong&gt;App Key&lt;/strong&gt;; in "Integration Code" you can find the integration instructions for developers.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: Have the App Report the Device Token
&lt;/h2&gt;

&lt;p&gt;Following the guidance in the "Device Integration Instructions", ask the app developer to add Push Notifications under Signing &amp;amp; Capabilities in Xcode and put the sample method into the AppDelegate, so that the app calls the reporting API after obtaining the APNs token. Devices that report successfully automatically appear in the "Device Library" tab, where you can search by note/token/tag, and also manually add device tokens or edit tags. During testing, choose the LAN address where the phone is located, and make sure the phone and your computer are on the same Wi-Fi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Compose and Send a Notification
&lt;/h2&gt;

&lt;p&gt;On the "Send" tab:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the push channel to use.&lt;/li&gt;
&lt;li&gt;Fill in the title, content, sound (default alert/silent) and badge number; when you need finer control, switch to "Advanced Mode" to edit the raw JSON Payload directly.&lt;/li&gt;
&lt;li&gt;Choose the send target: all devices / by tag / specific devices.&lt;/li&gt;
&lt;li&gt;After confirming the number of valid devices the notification will be sent to, click "Send Now"; when it finishes, the number of successful/failed devices is displayed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: View Delivery Results
&lt;/h2&gt;

&lt;p&gt;The "History" tab records the time, content, target and result of each send. Click "Details" to see the per-device delivery report (success/failed/delivered and the failure reason); you can also "Resend" a history entry directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Thing to Note
&lt;/h2&gt;

&lt;p&gt;Deleting a push channel &lt;strong&gt;also deletes the device library and send history under that channel, and the App Key becomes invalid immediately&lt;/strong&gt;. This operation cannot be undone, so if you only want to pause pushing, do not delete the channel.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
    </item>
    <item>
      <title>TraceEagle iOS Packet Capture Tutorial: How to Choose the Three iPhone No-Jailbreak Capture Methods</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Fri, 11 Sep 2026 10:04:33 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/traceeagle-ios-packet-capture-tutorial-how-to-choose-the-three-iphone-no-jailbreak-capture-methods-4ajb</link>
      <guid>https://dev.to/uikit_ninja/traceeagle-ios-packet-capture-tutorial-how-to-choose-the-three-iphone-no-jailbreak-capture-methods-4ajb</guid>
      <description>&lt;h1&gt;
  
  
  iOS Packet Capture
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;This guide teaches you how to capture packets on &lt;strong&gt;iPhone / iPad&lt;/strong&gt;: connect a data cable to a computer, choose a mode, and start capturing—&lt;strong&gt;no jailbreak throughout&lt;/strong&gt;. From 'zero-config visibility into system requests' to 'full device traffic' to 'complete plaintext for a single app', each of the three modes has its own steps. This guide walks you through them step by step.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. When to Use It and How to Choose Among the Three Modes
&lt;/h2&gt;

&lt;p&gt;After you select &lt;strong&gt;iOS&lt;/strong&gt; in &lt;strong&gt;New Session&lt;/strong&gt; for iOS packet capture, you will be asked to choose one of three. First pick the one you want from the table below, then follow the corresponding section:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your Goal&lt;/th&gt;
&lt;th&gt;Which Mode&lt;/th&gt;
&lt;th&gt;What You Can See&lt;/th&gt;
&lt;th&gt;Certificate / Re-signing Needed?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Quickly see which HTTPS requests this device sends (URL / status / headers)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;System-level Capture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Even for regular apps, you can see request URLs and headers (Body not visible)&lt;/td&gt;
&lt;td&gt;Only install a device diagnostics profile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All traffic from the entire device (including non-HTTP, handshake / SNI)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;NIC Capture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full data, ciphertext by default; can do targeted decryption for a specified app&lt;/td&gt;
&lt;td&gt;Not needed to view ciphertext; re-sign only to decrypt plaintext for a specific app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Complete plaintext send/receive (including Body)&lt;/strong&gt; for an app&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;App-level Capture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complete plaintext for a single app&lt;/td&gt;
&lt;td&gt;Target app must be re-signed with a development certificate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;System-level capture is the easiest&lt;/strong&gt;: for regular apps and App Store apps, you can also see which HTTPS addresses they request—no CA certificate, no proxy, and no fear of certificate pinning. To quickly investigate 'which endpoints does this app actually connect to', start with it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In addition to the above three, iPhone / iPad can also use proxy capture: point the device's Wi-Fi proxy to this computer, install a root certificate, and you can capture HTTPS plaintext just like on a computer, with full capabilities such as rewrite and replay. Suitable for debugging apps that use the system proxy.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Prerequisites (Common to All Three Modes)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TraceEagle is installed and started (on first launch, just accept the system permissions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect iPhone / iPad to the computer with a data cable&lt;/strong&gt;, and tap &lt;strong&gt;Trust&lt;/strong&gt; when prompted on the device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No jailbreak required&lt;/strong&gt;: all three modes are for non-jailbroken devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Newer systems are also supported&lt;/strong&gt;: iOS 17 and later can still connect and capture normally.&lt;/li&gt;
&lt;li&gt;Prepare certificates / re-signing according to the mode (no rush if you do not have them; the tool will guide you when needed):

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System-level capture&lt;/strong&gt;: install a &lt;strong&gt;device diagnostics profile&lt;/strong&gt; (once is enough).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NIC capture&lt;/strong&gt;: to view only ciphertext and addresses, &lt;strong&gt;no&lt;/strong&gt; certificate is needed; to decrypt plaintext for an app, you must re-sign that app with a &lt;strong&gt;development certificate&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App-level capture&lt;/strong&gt;: the target app must be re-signed with a &lt;strong&gt;development certificate&lt;/strong&gt; (App Store and system apps must be re-signed first before they can be targets).&lt;/li&gt;
&lt;li&gt;For detailed steps to install certificates / profiles, see Certificate Installation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Select a Device: The First Common Step for All Three Modes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a new session, and select &lt;strong&gt;iOS&lt;/strong&gt; for &lt;strong&gt;Target&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select your phone in the &lt;strong&gt;Device&lt;/strong&gt; dropdown; if it does not appear right after plugging in, click &lt;strong&gt;Refresh&lt;/strong&gt;. If the same device also appears over the network, identifying the &lt;strong&gt;USB&lt;/strong&gt; entry by &lt;strong&gt;USB / Network&lt;/strong&gt; is the most reliable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;strong&gt;Mode&lt;/strong&gt;, select one of &lt;strong&gt;NIC Capture / System-level Capture / App-level Capture&lt;/strong&gt;, then read the corresponding section below.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  4. System-level Capture — Easiest, Works with Regular Apps
&lt;/h2&gt;

&lt;p&gt;If you want to quickly see 'which HTTPS requests this iPhone sends' without installing a CA certificate, setting a proxy, or dealing with certificate pinning, choose this mode.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select &lt;strong&gt;System-level Capture&lt;/strong&gt; for Mode.&lt;/li&gt;
&lt;li&gt;If you have not installed the &lt;strong&gt;device diagnostics profile&lt;/strong&gt;, install it once as prompted (see Certificate Installation); skip if already installed.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt; to start, then operate the app you want to observe normally on the phone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How much you can see depends on the target app:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regular apps, App Store apps&lt;/strong&gt;: usually you can see the &lt;strong&gt;request method, full URL (HTTPS addresses are also plaintext), status code, request headers, and response headers&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apps signed with a development certificate&lt;/strong&gt;: even the &lt;strong&gt;complete request / response Body&lt;/strong&gt; is visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. NIC Capture — See Everything on This Device
&lt;/h2&gt;

&lt;p&gt;To view &lt;strong&gt;all network traffic of the entire device&lt;/strong&gt;—unrestricted by app or protocol, including non-HTTP QUIC and custom protocols—choose this mode.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select &lt;strong&gt;NIC Capture&lt;/strong&gt; for Mode.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt; to start. By default, what is captured is &lt;strong&gt;ciphertext packets + metadata&lt;/strong&gt; (target address, port, and the SNI hostname in the TLS handshake)—enough to see 'where this device connects and with what protocol'.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To see plaintext for a specific app&lt;/strong&gt;: check &lt;strong&gt;Decrypt this Program&lt;/strong&gt; for that app to decrypt its plaintext; the prerequisite is that the app has been re-signed with a &lt;strong&gt;development certificate&lt;/strong&gt; (see Certificate Installation).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  6. App-level Capture — Complete Plaintext for a Single App
&lt;/h2&gt;

&lt;p&gt;To obtain the &lt;strong&gt;complete plaintext (including Body)&lt;/strong&gt; sent and received by &lt;strong&gt;one specific app&lt;/strong&gt;—it takes data from inside the app, and certificate pinning cannot block it—choose this mode.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select &lt;strong&gt;App-level Capture&lt;/strong&gt; for Mode.&lt;/li&gt;
&lt;li&gt;Select the target app from the app list. Only apps that have been &lt;strong&gt;re-signed with a development certificate&lt;/strong&gt; are selectable; the rest are grayed out—if the app you want to capture is gray, re-sign it first (see Certificate Installation).&lt;/li&gt;
&lt;li&gt;If you also want to capture &lt;strong&gt;early startup&lt;/strong&gt; traffic, you can first &lt;strong&gt;close the target app, then click Create and reopen it&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt; to start, then operate the app on the phone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If plaintext cannot be decrypted&lt;/strong&gt;: turn on the &lt;strong&gt;socket traffic&lt;/strong&gt; switch as a fallback—for apps whose plaintext cannot be obtained through the regular method, use a lower-level path to get data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  7. Verify: Confirm You Have Captured Traffic
&lt;/h2&gt;

&lt;p&gt;After creation, a session tab opens. Operate the corresponding app on the phone, and requests will &lt;strong&gt;appear in the left list in real time&lt;/strong&gt;. Click any entry to view details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System-level Capture&lt;/strong&gt;: you can see the request method, full URL, status code, and request / response headers (for apps signed with a development certificate, you can also see the Body).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NIC Capture&lt;/strong&gt;: you can see the target address, port, and SNI hostname; for an app with &lt;strong&gt;Decrypt this Program&lt;/strong&gt; checked, the response is readable plaintext.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App-level Capture&lt;/strong&gt;: the request line, request headers, and Body are all present, and the response is plaintext rather than garbled ciphertext.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Cannot Connect / Cannot Capture? Troubleshoot Item by Item
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely Cause&lt;/th&gt;
&lt;th&gt;What to Do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Phone not visible in the Device dropdown&lt;/td&gt;
&lt;td&gt;Not plugged in properly, not trusted, or just plugged in and not enumerated yet&lt;/td&gt;
&lt;td&gt;Try another data cable / USB port, tap &lt;strong&gt;Trust&lt;/strong&gt; on the phone, then click &lt;strong&gt;Refresh&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two entries for the device; which one to choose&lt;/td&gt;
&lt;td&gt;The same device is on both USB and network&lt;/td&gt;
&lt;td&gt;Prefer the &lt;strong&gt;USB&lt;/strong&gt; entry; it is the most reliable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System-level capture creates no entries&lt;/td&gt;
&lt;td&gt;Device diagnostics profile is not installed or not effective&lt;/td&gt;
&lt;td&gt;Install the profile as described in Certificate Installation, then create the session again&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System-level capture shows only addresses and headers, no Body&lt;/td&gt;
&lt;td&gt;Target is a regular app / App Store app&lt;/td&gt;
&lt;td&gt;This is a limitation of system diagnostic logs; for a complete Body, switch to &lt;strong&gt;App-level Capture&lt;/strong&gt; (the app must be re-signed first)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NIC capture is all ciphertext; plaintext is not visible&lt;/td&gt;
&lt;td&gt;Targeted decryption was not enabled for the target app&lt;/td&gt;
&lt;td&gt;Check &lt;strong&gt;Decrypt this Program&lt;/strong&gt; for the app; if it cannot be checked, the app has not been re-signed with a development certificate—re-sign it first (Certificate Installation)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Target app is gray and unselectable in App-level Capture&lt;/td&gt;
&lt;td&gt;The app has not been re-signed with a development certificate&lt;/td&gt;
&lt;td&gt;Re-sign it first (both App Store / system apps must be re-signed first), see Certificate Installation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App-level Capture captures traffic but cannot decrypt plaintext&lt;/td&gt;
&lt;td&gt;The app uses a proprietary / statically linked library&lt;/td&gt;
&lt;td&gt;Turn on the &lt;strong&gt;socket traffic&lt;/strong&gt; switch as a fallback and use a lower-level path to get data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Want to capture requests from the first few seconds after app launch&lt;/td&gt;
&lt;td&gt;The session was opened after the app was already running&lt;/td&gt;
&lt;td&gt;Close the app first, create the session, then reopen it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Certificate / profile is installed but capture still fails&lt;/td&gt;
&lt;td&gt;The profile has not been trusted in the phone's Settings&lt;/td&gt;
&lt;td&gt;Go to the phone's &lt;strong&gt;Settings&lt;/strong&gt; and trust the corresponding profile / certificate, then retry; see Certificate Installation for details&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to read captured data, switch views, and decode: see Data Viewing and Decoding.&lt;/li&gt;
&lt;li&gt;To modify while viewing, edit and resend requests, or intercept and manually modify them: see Rule Rewriting and Breakpoint Interception, Request Construction and Replay.&lt;/li&gt;
&lt;li&gt;For private / proprietary protocols and teaching it how to read them yourself: see Custom Protocol Decoding.&lt;/li&gt;
&lt;li&gt;To capture HTTPS plaintext on a phone like on a computer and use full rewrite/replay capabilities: see Proxy Capture with Certificate Installation.&lt;/li&gt;
&lt;li&gt;To capture Android devices: see Android Capture.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mobile</category>
      <category>software</category>
      <category>networking</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>iOS Provisioning Profile Management: Create, Regenerate, and Clean Invalid Profiles</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Thu, 10 Sep 2026 10:05:41 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/ios-provisioning-profile-management-create-regenerate-and-clean-invalid-profiles-3d6b</link>
      <guid>https://dev.to/uikit_ninja/ios-provisioning-profile-management-create-regenerate-and-clean-invalid-profiles-3d6b</guid>
      <description>&lt;h1&gt;
  
  
  Provisioning Profile
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Requires a paid Apple Developer Program membership.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A provisioning profile (&lt;code&gt;Provisioning Profile&lt;/code&gt;, i.e. &lt;code&gt;.mobileprovision&lt;/code&gt;) is used to build an App. &lt;strong&gt;You need one for development and one for distribution.&lt;/strong&gt; After modifying the permission configuration of a Bundle ID, you must regenerate and download the provisioning profile; push notifications do not require a provisioning profile.&lt;/p&gt;

&lt;p&gt;A provisioning profile is bound to one Bundle ID and linked to several certificates and devices (only distribution profiles require devices).&lt;/p&gt;

&lt;h2&gt;
  
  
  Provisioning Profile Types
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;iOS / tvOS / macOS / DriverKit App Development&lt;/td&gt;
&lt;td&gt;Install development builds on test devices (the iOS type also covers iPadOS, watchOS, and visionOS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS / tvOS Ad Hoc Distribution&lt;/td&gt;
&lt;td&gt;Install the app on a limited number of registered devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS / tvOS / macOS App Store Distribution&lt;/td&gt;
&lt;td&gt;Submit the app to the App Store / Mac App Store&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS Direct Distribution (Developer ID)&lt;/td&gt;
&lt;td&gt;Distribute Mac apps directly outside the Mac App Store&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS / tvOS Enterprise In-House Distribution&lt;/td&gt;
&lt;td&gt;Distribute apps within an organization; requires the Apple Developer Enterprise Program&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Create a Provisioning Profile
&lt;/h2&gt;

&lt;p&gt;Open &lt;strong&gt;Appuploader&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click "New Provisioning Profile" and enter a name.&lt;/li&gt;
&lt;li&gt;Select the type (this determines the available certificates and devices).&lt;/li&gt;
&lt;li&gt;Select the associated Bundle ID; if you don't have the required Bundle ID yet, click "New Bundle ID" directly.&lt;/li&gt;
&lt;li&gt;Select the associated certificates (multiple selections allowed, or choose "All Certificates").&lt;/li&gt;
&lt;li&gt;If it is a distribution type that requires devices, select the associated devices (multiple selections allowed, or choose "All Devices"; you can also click "Register Device" directly).&lt;/li&gt;
&lt;li&gt;Once submitted, the provisioning profile is created and can be downloaded from the list.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Regenerate and Clean Up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regenerate&lt;/strong&gt;: After a profile's certificates or devices change, click "Regenerate" — the profile is deleted and recreated with the currently valid certificates and all enabled devices. If the profile has no associated Bundle ID, it cannot be regenerated automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Up Invalid&lt;/strong&gt;: Delete all invalid (INVALID / EXPIRED) provisioning profiles with one click; they can be recreated at any time afterward.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Search
&lt;/h2&gt;

&lt;p&gt;The list supports searching by name / type / UUID.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
    </item>
    <item>
      <title>No-Login File Viewing &amp; App Store Submission: A Practical Guide</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Wed, 09 Sep 2026 09:31:19 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/no-login-file-viewing-app-store-submission-a-practical-guide-563o</link>
      <guid>https://dev.to/uikit_ninja/no-login-file-viewing-app-store-submission-a-practical-guide-563o</guid>
      <description>&lt;h1&gt;
  
  
  Appuploader: Files &amp;amp; Submission
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;No Apple ID login required.&lt;/strong&gt; Supports viewing information in &lt;code&gt;.plist&lt;/code&gt;, &lt;code&gt;.mobileprovision&lt;/code&gt;, &lt;code&gt;.p12&lt;/code&gt;, and &lt;code&gt;.ipa&lt;/code&gt; files; submitting to App Store; installing to connected iOS devices; and exporting public/private keys from a &lt;code&gt;.p12&lt;/code&gt; file. Maximum single file size: 2.9GB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uploading Files
&lt;/h2&gt;

&lt;p&gt;Click &lt;strong&gt;Add File&lt;/strong&gt; to select a file, or drag and drop files directly into the list area (multiple files can be dropped at once). Uploaded files appear in the list with their types labeled (Plist File / Provisioning Profile / P12 Certificate / IPA Package / Other).&lt;/p&gt;

&lt;h2&gt;
  
  
  Viewing File Content
&lt;/h2&gt;

&lt;p&gt;Open &lt;strong&gt;Appuploader&lt;/strong&gt;, click a file to enter the viewer. Different file types show different information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Plist&lt;/strong&gt;: Displays XML content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provisioning Profile (.mobileprovision)&lt;/strong&gt;: Bundle name, display name, version, minimum OS, embedded provisioning profile details, signing certificate, CA certificate chain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;P12 Certificate&lt;/strong&gt;: If encrypted, enter the export password to parse (leave blank if no password). After parsing, you can export the public key PEM or export the private key PEM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPA Package&lt;/strong&gt;: Displays signing information, including whether it is signed, embedded provisioning profile, and signing certificate. It also indicates whether the information source is “binary code signature (actual signing result)” or “embedded provisioning profile (allowed scopes only)” — these may differ. Note that IPA packages downloaded from the App Store have their provisioning profile removed by Apple; only development, Ad Hoc, and enterprise distribution packages include provisioning profiles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Submitting IPA to App Store
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;On first use, you need to &lt;strong&gt;set an Upload-Specific Password&lt;/strong&gt;: use your Apple ID and an &lt;strong&gt;App-Specific Password&lt;/strong&gt; (not your login password). Go to Account Management &amp;amp; Security → App-Specific Passwords, generate one (format: &lt;code&gt;xxxx-xxxx-xxxx-xxxx&lt;/code&gt;). Note that what you manually name is only the password label; the auto-generated string is the password you need to fill in.&lt;/li&gt;
&lt;li&gt;Select an IPA file and click &lt;strong&gt;Submit to App Store&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The submission process does not require fully logging into that Apple account and will not trigger two-factor authentication.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installing to a Phone
&lt;/h2&gt;

&lt;p&gt;Select an IPA file and click &lt;strong&gt;Install to Phone&lt;/strong&gt;. Two methods are provided:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Connected Device Installation&lt;/strong&gt;: Connect and unlock the device with a USB cable, and make sure you trust this computer. The IPA must include the device's UDID to install successfully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QR-Code Installation (LAN)&lt;/strong&gt;: Connect the iPhone/iPad and computer to the same Wi-Fi, use the system camera to scan the QR code, and tap the installation prompt that appears at the top.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before installation, the system automatically detects the provisioning profile type (Development / Ad Hoc / Enterprise Distribution / App Store). If an issue could cause installation to fail (e.g., the device UDID is not included in the provisioning profile), it prompts with the specific problem, and you can choose &lt;strong&gt;Install Anyway&lt;/strong&gt; or &lt;strong&gt;Cancel Installation&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You can delete uploaded files at any time.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mobile</category>
      <category>software</category>
    </item>
    <item>
      <title>Packet Capture Tool Comparison: Charles, Fiddler, TraceEagle, Wireshark, and Proxyman</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Tue, 08 Sep 2026 09:33:54 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/packet-capture-tool-comparison-charles-fiddler-traceeagle-wireshark-and-proxyman-1ihp</link>
      <guid>https://dev.to/uikit_ninja/packet-capture-tool-comparison-charles-fiddler-traceeagle-wireshark-and-proxyman-1ihp</guid>
      <description>&lt;p&gt;Packet capture is one of the most common techniques developers use in daily debugging. There are many tools on the market, but each has a distinct positioning and applicable scenario, so choosing the right one can save a lot of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Charles: The Most Widely Used Proxy Packet Capture Tool
&lt;/h2&gt;

&lt;p&gt;Charles has the largest user base for HTTP/HTTPS packet capture. Its advantage lies in its low learning curve—after installing it on a Mac, configuring the proxy on your phone, and installing the certificate, you can see the request list within minutes. It supports Breakpoint interception to modify requests, Repeat for replaying requests, and Map Local/Remote for request mapping. Once SSL Proxying is configured with the target domains, HTTPS traffic can also be decrypted.&lt;/p&gt;

&lt;p&gt;Charles's limitations appear mainly in several scenarios: with SSL Pinning, proxy certificates are rejected by the client, leaving only handshake failure records; traffic from apps that ignore the system proxy is not captured; HTTP/3 and QUIC support is insufficient; and the certificate configuration flow on Windows is more complex than on Mac.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fiddler: The Main Packet Capture Tool in the Windows Ecosystem
&lt;/h2&gt;

&lt;p&gt;Fiddler is widely used on Windows. Its core strength is FiddlerScript—writing scripts in C# to customize request and response handling, which suits automated testing scenarios. It supports breakpoint debugging and request construction. A built-in performance analysis panel shows request latency and bandwidth usage.&lt;/p&gt;

&lt;p&gt;Fiddler's shortcomings are also obvious: on macOS only a limited-feature Beta version exists, and Windows remains the primary platform; HTTPS decryption requires manually configuring certificates, with more steps than Charles; the interface feels dated, and filtering is less convenient when handling large volumes of data.&lt;/p&gt;

&lt;h2&gt;
  
  
  TraceEagle: Covers More Edge Cases
&lt;/h2&gt;

&lt;p&gt;TraceEagle takes a different approach from the tools mentioned above. It builds on proxy-based capture and fills the blind spots of other tools: apps that ignore the system proxy can be captured directly from the network interface or via in-app stream extraction; in SSL Pinning scenarios, there is no need to swap certificates in the middle—plaintext can be obtained directly from inside the app; HTTP/3 and QUIC are handled via three modes: downgrade capture, fidelity transparent passthrough, and actual decryption.&lt;/p&gt;

&lt;p&gt;The workflow after packets are captured is also more complete—you can set breakpoints and modify requests in the same interface, right-click to run load tests and view p99 tail latency, compare differences line by line, and reverse-engineer OpenAPI documents. It supports packet capture on iOS without jailbreak and on Android without installing certificates, and runs on Windows, macOS, and Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wireshark: The Most Comprehensive Protocol Analyzer
&lt;/h2&gt;

&lt;p&gt;Wireshark is unrivaled in the depth of protocol analysis, supporting parsing of thousands of protocols. Its filter expressions are powerful, allowing you to combine source IP, port, protocol, and other conditions to locate specific traffic. It is the standard tool for troubleshooting TCP retransmissions and TLS handshake details.&lt;/p&gt;

&lt;p&gt;To capture iOS mobile traffic with Wireshark, you need to use the &lt;code&gt;rvictl&lt;/code&gt; command on a Mac to create a virtual interface; it cannot be used directly on Windows. Moreover, Wireshark does not handle HTTPS decryption—you must export keys separately. For everyday API debugging, Wireshark's operational workflow is longer than that of proxy-based tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proxyman: A Modern Choice on macOS
&lt;/h2&gt;

&lt;p&gt;Proxyman is a packet capture tool that has become popular on macOS in recent years. Its interface is more modern than Charles and Fiddler, and the visual configuration for request filtering rules is more intuitive. It supports grouping by domain, advanced search, and script extensions. In SSL Pinning scenarios, it can be solved by installing a root certificate together with iOS's SSL Kill Switch.&lt;/p&gt;

&lt;p&gt;Proxyman's limitation is that it supports macOS only, so Windows users cannot use it. HTTP/3 support is also limited. Its deep analysis capability and script flexibility are not as strong as Fiddler's.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selection Recommendations
&lt;/h2&gt;

&lt;p&gt;For simple HTTP API debugging in daily work, Charles or Proxyman is sufficient. In Windows environments where scripting capability is required, choose Fiddler. For deep dives into the TCP protocol layer, Wireshark is a must. When encountering edge cases such as certificate pinning, HTTP/3, or proprietary protocols in a project, adding TraceEagle to your toolchain fills in the blind spots.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
      <category>networking</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Developing iOS Without a Mac: Several Feasible Solutions Using Cloud Services and Built-in Compilers</title>
      <dc:creator>UIKit_Ninja</dc:creator>
      <pubDate>Tue, 08 Sep 2026 08:58:45 +0000</pubDate>
      <link>https://dev.to/uikit_ninja/developing-ios-without-a-mac-several-feasible-solutions-using-cloud-services-and-built-in-compilers-1n3i</link>
      <guid>https://dev.to/uikit_ninja/developing-ios-without-a-mac-several-feasible-solutions-using-cloud-services-and-built-in-compilers-1n3i</guid>
      <description>&lt;p&gt;The most rigid limitation of iOS development is that you must use a Mac. But in practical work, there are always scenarios that cannot avoid this problem—your company assigns you a Windows laptop, your budget is too limited to afford a Mac, or you are only temporarily participating in an iOS project. Are there feasible ways to do iOS development without a Mac? Sorted by cost and experience, a few options are available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud Mac Services
&lt;/h2&gt;

&lt;p&gt;Services like MacStadium and MacinCloud offer remote Mac servers billed by the hour or month. Accessing them remotely gives you a full Xcode environment; compiling, packaging, and uploading all work fine. The advantage is that the experience is almost identical to a real Mac; the downside is that latency depends on network quality, and long-term costs are not cheap.&lt;/p&gt;

&lt;p&gt;Another route is building your own Hackintosh, installing macOS on compatible PC hardware. This lets you use Xcode, and performance can be better than a low-end Mac. However, installation and maintenance can be troublesome, system updates may break it, and hardware compatibility is limited.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remote Mac + Local Coding
&lt;/h2&gt;

&lt;p&gt;The most flexible solution: write code locally in Windows or Linux using VS Code, then connect to a remote Mac for compilation. Use SSH to connect to the remote Mac and use xcodebuild to package, or use VS Code's Remote-SSH extension to edit code directly in the remote environment.&lt;/p&gt;

&lt;p&gt;The coding experience is free, but switching between compilation and debugging across two environments can be tedious. Every time you change code, you have to push it to the remote; when errors occur, you switch back to the local editor. Certificate and provisioning profile management also depends on the remote Mac. This works if you are only occasionally changing a few lines, but efficiency drops under frequent iterations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hackintosh
&lt;/h2&gt;

&lt;p&gt;Hackintosh is the practice of installing macOS on an ordinary PC. A mid-range desktop running Xcode may outperform a Mac mini at a similar price. During installation, you need to pick compatible hardware, configure the bootloader, and work through driver issues. After major macOS releases, you may need to redo the bootloader configuration.&lt;/p&gt;

&lt;p&gt;Hackintosh exists in a legal gray area—macOS's license agreement does not permit running it on non-Apple hardware. It is not recommended for official team use, though it is a good option for personal learning and experiments.&lt;/p&gt;

&lt;h2&gt;
  
  
  KXApp Built-in Compiler
&lt;/h2&gt;

&lt;p&gt;KXApp goes about things differently from the above options—it does not need a system-level installation of macOS; it runs directly on Windows or Linux. It bundles an iOS compilation toolchain, covering everything from creating Swift/Objective-C/Flutter projects, compiling and building, to running and debugging on a real device, all inside the same tool.&lt;/p&gt;

&lt;p&gt;With KXApp, iOS development does not require a remote Mac, a virtual machine, or a Hackintosh. Connect your phone via USB, and you can directly build and install onto the physical device; the tool handles code signing and deployment automatically. iOS compilation for Flutter projects is also supported out of the box, saving you the trouble of configuring Flutter and Xcode integration.&lt;/p&gt;

&lt;p&gt;That said, an objective review is warranted: KXApp is suitable for rapid prototyping, Flutter project validation, and lightweight iOS development. For complex project configuration and Instruments performance analysis, Xcode remains essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing a Solution
&lt;/h2&gt;

&lt;p&gt;If budget is not a concern, a cloud Mac offers the closest experience. If cost-effectiveness is what you care about, you can consider building a Hackintosh. If you mainly work with Flutter or do lightweight iOS development, KXApp runs directly on Windows, saving the overhead of a Mac environment.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
      <category>javascript</category>
      <category>flutter</category>
    </item>
  </channel>
</rss>
