<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://pyckamil.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://pyckamil.github.io/" rel="alternate" type="text/html" /><updated>2026-02-11T20:00:27+00:00</updated><id>https://pyckamil.github.io/feed.xml</id><title type="html">Kamil Pyc</title><subtitle>Personal blog about programming on iOS and Mac.</subtitle><author><name>Kamil Pyć</name></author><entry><title type="html">Deprecating Frameworks</title><link href="https://pyckamil.github.io/programming,/framework,/xcode/2020/11/21/deprecating-frameworks.html" rel="alternate" type="text/html" title="Deprecating Frameworks" /><published>2020-11-21T18:10:15+00:00</published><updated>2020-11-21T18:10:15+00:00</updated><id>https://pyckamil.github.io/programming,/framework,/xcode/2020/11/21/deprecating-frameworks</id><content type="html" xml:base="https://pyckamil.github.io/programming,/framework,/xcode/2020/11/21/deprecating-frameworks.html"><![CDATA[<p>I can imagine that if Framework was an API we would probably see it marked as <code class="language-plaintext highlighter-rouge">@available(*, deprecated, message: "Use XCFramework now!")</code> when XCFrameworks was introduced in last year’s WWDC.</p>

<p>Although I couldn’t find direct meantion of it in documentation or during presentations everything points into that direction.</p>

<h2 id="xcframework">XCFramework</h2>

<p>XCFramework is only way to support Mac Catalyst since Fat Framework don’t contain multiple x86 slices, but since Catalyst is something new and only fraction of apps supports it isn’t priority to support - for example Carthage <a href="https://github.com/Carthage/Carthage/issues/2799">request for Catalyst support</a> is opened since June 2019.</p>

<p>Then Swift 5.3 brings binary dependencies capability to SPM and those can only be XCFrameworks. But again - not everyone uses SPM and one could stick to Framework till this point. But things have changed when Apple Silicone Macs were introduced last month.</p>

<h2 id="status-quo">Status quo</h2>

<p>Since the first iPhoneOS SDK when we were building for a real device we used <code class="language-plaintext highlighter-rouge">iphoneos</code> sdk and ARM architecture, when we select a simulator we would use <code class="language-plaintext highlighter-rouge">iphonesimulator</code> sdk and x86 architecture. Then we could use <code class="language-plaintext highlighter-rouge">lipo</code> to combine them into Fat Framework that would work with both device and simulator. This is how Carthage works and most precompiled frameworks are distributed.</p>

<p>To illustrate - we have:</p>

<ul>
  <li>ARM  ↔️ iphoneos</li>
  <li>x86 ↔️ iphonesimulator</li>
</ul>

<p>This is where Apple Silicone break this order adding third pair:</p>

<ul>
  <li>ARM ↔️ iphonesimulator</li>
</ul>

<h2 id="xcode-12">Xcode 12</h2>

<p>One thing changed in Xcode 12, one that is not clearly visible and many developers was surprised to discover.</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Did anyone encounter/found a fix for the issue where you build for Catalyst in Xcode 12.2 and Xcode just MUST build an arm64 version, ignoring the &quot;build active architecture only” setting? I can work around by always building all archs, but dang it so slow. <a href="https://t.co/tjnSzNinxa">pic.twitter.com/tjnSzNinxa</a></p>&mdash; Peter Steinberger (@steipete) <a href="https://twitter.com/steipete/status/1324297285489119237?ref_src=twsrc%5Etfw">November 5, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>Let’s build a Framework target for simulator and investigate it:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell">lipo <span class="nt">-archs</span>  Sample.framework/Sample
x86_64 arm64</code></pre></figure>

<p>By default Xcode will build for both ARM and x86. This new behavior will break Carthage that uses <code class="language-plaintext highlighter-rouge">lipo</code> under the hood to produce Fat Framework.</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"><span class="nv">$lipo</span> <span class="nt">-create</span> iphoneos/Sample.framework/Sample iphonesimulator/Sample.framework/Sample 

fatal error: Sample.framework/Sample have the same architectures <span class="o">(</span>arm64<span class="o">)</span> and can<span class="s1">'t be in the same fat output file</span></code></pre></figure>

<p>Fortunatly there is <a href="https://github.com/Carthage/Carthage/blob/master/Documentation/Xcode12Workaround.md">document</a> describing how to exclude ARM architecture from building and basically restore how it worked in Xcode 11. Of course that will only work on Intel Macs, Apple Silicone users should wait for <a href="https://github.com/Carthage/Carthage/pull/3071">XCFramework support</a> to land.</p>

<h2 id="wrap-up">Wrap up</h2>

<p>If you distribute framework for other developers - please provide them with proper XCFramework with ARM simulator version so they can use simulator on there new Macs. I wish Apple would clearly state the need for migration to XCFrameworks so it would be done sooner - not when developers would start having compilation errors.</p>]]></content><author><name>Kamil Pyć</name></author><category term="programming," /><category term="framework," /><category term="xcode" /><summary type="html"><![CDATA[I can imagine that if Framework was an API we would probably see it marked as @available(*, deprecated, message: "Use XCFramework now!") when XCFrameworks was introduced in last year’s WWDC.]]></summary></entry><entry><title type="html">Everything wrong with XCFrameworks</title><link href="https://pyckamil.github.io/programming,/xcframework,/xcode/2020/05/09/everything-wrong-with-xcframeworks.html" rel="alternate" type="text/html" title="Everything wrong with XCFrameworks" /><published>2020-05-09T09:30:15+00:00</published><updated>2020-05-09T09:30:15+00:00</updated><id>https://pyckamil.github.io/programming,/xcframework,/xcode/2020/05/09/everything-wrong-with-xcframeworks</id><content type="html" xml:base="https://pyckamil.github.io/programming,/xcframework,/xcode/2020/05/09/everything-wrong-with-xcframeworks.html"><![CDATA[<p>Good old frameworks are dated back to time where there was only one platfrom and one language - Obj-C. Today we have multiple version of Swift and different platforms to support.</p>

<p>When XCFrameworks was introduced in last years WWDC I was really excited:</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">&quot;XCFrameworks make it possible to bundle a binary framework or library for multiple platforms —including iOS devices, iOS simulators, and UIKit for Mac — into a single distributable .xcframework bundle that your developers can use within their own applications.&quot; 😲</p>&mdash; Kamil Pyć (@KamilPyc) <a href="https://twitter.com/KamilPyc/status/1135628413279100929?ref_src=twsrc%5Etfw">June 3, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>I would like to share my experience with it and what roadblocks you can hit trying to replace Frameworks with XCFrameworks in you project.</p>

<p>Note: all of code and examples was run on Xcode 11.4.1. using Swift 5.2.</p>

<h2 id="creating-xcframeworks">Creating XCFrameworks</h2>

<p>Lets start from the begining - how to create XCFramework. With Frameworks that just a normal target workflow as you may know from creating app or test targets. Just select “New…” and pick Framework as target.</p>

<p><img src="/assets/images/framework_creation_xcode.png" alt="Framework in Xcode" /></p>

<p>I would expect that from this point one can select which architectures to include and then export <code class="language-plaintext highlighter-rouge">.xcframework</code>. But it doesn’t work this way.</p>

<p>In order to produce xcframework we need to export all of the frameworks and then combine them with <code class="language-plaintext highlighter-rouge">-create-xcframework</code> command.</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"> xcodebuild <span class="nt">-create-xcframework</span> <span class="se">\</span>
            <span class="nt">-framework</span> <span class="k">${</span><span class="nv">FRAMEWORK_SIMULATOR_DIR</span><span class="k">}</span>/<span class="k">${</span><span class="nv">1</span><span class="k">}</span>.framework <span class="se">\</span>
            <span class="nt">-framework</span> <span class="k">${</span><span class="nv">FRAMEWORK_DEVICE_DIR</span><span class="k">}</span>/<span class="k">${</span><span class="nv">1</span><span class="k">}</span>.framework <span class="se">\</span>
            <span class="nt">-framework</span> <span class="k">${</span><span class="nv">FRAMEWORK_MAC_DIR</span><span class="k">}</span>/<span class="k">${</span><span class="nv">1</span><span class="k">}</span>.framework <span class="se">\</span>
            <span class="nt">-output</span> <span class="k">${</span><span class="nv">OUTPUT_DIR_PATH</span><span class="k">}</span>/xcframeworks/<span class="k">${</span><span class="nv">1</span><span class="k">}</span>.xcframework</code></pre></figure>

<p>You can check out full <a href="https://github.com/bielikb/xcframeworks/blob/master/scripts/create_xcframeworks_catalina.sh">create script on Github</a> created by Boris Bielik - it’s over 100 lines of code. Update: Boris created convinient <a href="https://github.com/bielikb/xcframeworks#Create-xcframework-using-fastlane-plugin">Fastlane plugin</a> that wraps this boilerplate up nicely.</p>

<p>I think that this over complication can be one of the reasons why XCFrameworks are <a href="https://github.com/Carthage/Carthage/pull/2801">still not supported by Carthage</a>.</p>

<h2 id="xcode">Xcode</h2>

<p>On a first glance usage isn’t different than how we work with standard frameworks. Just add it to target’s “Frameworks and Libraries” section in general tab.</p>

<p><img src="/assets/images/xcframework-general-tab.png" alt="Framework in Xcode" /></p>

<p>After building app in build log we can find out that XCFrameworks get different treatment than Frameworks.</p>

<p>There is a special <code class="language-plaintext highlighter-rouge">ProcessXCFrameworkLibrary</code> step that’s extracts correct <code class="language-plaintext highlighter-rouge">.framework</code> from all architectures contained in xcframework bundle based on target architecture.</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell">ProcessXCFrameworkLibrary PromisesObjC.xcframework/ios-i386_x86_64-simulator/PromisesObjC.framework /Users/kamilpyc/Library/Developer/Xcode/DerivedData/NotchIt-axosvlxgvlvyerffinztzmvrhkfp/Build/Products/Debug-iphonesimulator/PromisesObjC.framework <span class="o">(</span><span class="k">in </span>target <span class="s1">'TargetB'</span> from project <span class="s1">'NotchIt'</span><span class="o">)</span></code></pre></figure>

<p>Because of that Xcode need to have explicit list of xcframeworks to process and <code class="language-plaintext highlighter-rouge">FRAMEWORK_SEARCH_PATHS</code> does not work.
Xcode wants to optimise the usage of <code class="language-plaintext highlighter-rouge">ProcessXCFrameworkLibrary</code> and ther is only one call per single <code class="language-plaintext highlighter-rouge">xcframework</code>. That’s will make build to fail in pretty common usage case.
Let’s say we have target <code class="language-plaintext highlighter-rouge">ModelA.framework</code> and <code class="language-plaintext highlighter-rouge">ModelB.framework</code> that links same <code class="language-plaintext highlighter-rouge">ModelCore.xcframework</code>. Xcode selects one of this targets to include the <code class="language-plaintext highlighter-rouge">ProcessXCFrameworkLibrary</code> step and if this selected target will start after another target utilising same xcframework build will simply fail with <code class="language-plaintext highlighter-rouge">Framework not found ModelCore</code>. I took me some time to figure out this race going on when my builds fails randomly 50% of time.</p>

<p><strong>WWDC2020 update:</strong>
Xcode 12 fixes the race condition bug:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">Fixed a race condition where multiple targets using the same XCFramework could result in non-deterministic build failures.
	</code></pre></figure>

<h2 id="swift">Swift</h2>
<p>In order to produce Swift libary that’s support module stability, frameworks needs to be created with <code class="language-plaintext highlighter-rouge">BUILD_LIBRARY_FOR_DISTRIBUTION</code> turned on:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell">xcodebuild archive <span class="se">\</span>
    <span class="nt">-workspace</span> XCFrameworks.xcworkspace <span class="se">\</span>
    <span class="nt">-scheme</span> <span class="k">${</span><span class="nv">1</span><span class="k">}</span> <span class="se">\</span>
    <span class="nt">-destination</span> <span class="s2">"</span><span class="k">${</span><span class="nv">2</span><span class="k">}</span><span class="s2">"</span> <span class="se">\</span>
    <span class="nt">-archivePath</span> <span class="s2">"</span><span class="k">${</span><span class="nv">3</span><span class="k">}</span><span class="s2">"</span> <span class="se">\</span>
    <span class="nv">SKIP_INSTALL</span><span class="o">=</span>NO <span class="se">\</span>
    <span class="nv">BUILD_LIBRARY_FOR_DISTRIBUTION</span><span class="o">=</span>YES</code></pre></figure>

<p>Under the hood this will pass <code class="language-plaintext highlighter-rouge">-enable-library-evolution</code> flag to Swift Compiler. That have couple of implications:</p>
<ul>
  <li>Code is compiled differently. When I tried to replace <a href="https://github.com/apollographql/apollo-ios">Apollo</a> framework with precompiled xcframework version app started crashing with <code class="language-plaintext highlighter-rouge">swift_getEnumCaseMultiPayload.cold.1</code></li>
  <li>If you have any enums you either have to mark them <code class="language-plaintext highlighter-rouge">@frozen</code> or handle default case on usage. Unfortunalty that make it impossible to simply replace <code class="language-plaintext highlighter-rouge">xcframework</code> with <code class="language-plaintext highlighter-rouge">.framework</code> in case any code needs to be debugged or profiled.</li>
  <li>Generated <code class="language-plaintext highlighter-rouge">.swiftinterface</code> file is corrupted. This was is <a href="https://forums.swift.org/t/generated-swiftinterface-has-wrong-content/28543/3">already reported</a> but not solved, so you cannot build SwiftyJSON or RxSwift as xcframework.</li>
</ul>

<h2 id="wrap-up">Wrap up</h2>
<p>In summary, there are few things that can block developers from using XCFrameworks expecially with Swift projects. That could explain why they are not widely popular on iOS. We are one month ahead of WWDC and I hope those get issues got resolved, because XCFrameworks are great step ahead of Framework.</p>]]></content><author><name>Kamil Pyć</name></author><category term="programming," /><category term="xcframework," /><category term="xcode" /><summary type="html"><![CDATA[Good old frameworks are dated back to time where there was only one platfrom and one language - Obj-C. Today we have multiple version of Swift and different platforms to support.]]></summary></entry><entry><title type="html">TIL: SwiftUI on Mac</title><link href="https://pyckamil.github.io/programming/2020/05/07/swiftui_on_mac.html" rel="alternate" type="text/html" title="TIL: SwiftUI on Mac" /><published>2020-05-07T21:30:15+00:00</published><updated>2020-05-07T21:30:15+00:00</updated><id>https://pyckamil.github.io/programming/2020/05/07/swiftui_on_mac</id><content type="html" xml:base="https://pyckamil.github.io/programming/2020/05/07/swiftui_on_mac.html"><![CDATA[<p>WWDC is near by, is good to catch up with stuff that is had on my TODO list - SwiftUI. I was tempted to try it on Mac to see how it manages to hide all of the complexity of AppKit.</p>

<p>I have mixed filling - right now SwifUI is great way to describe a layout, view hierachy and state managment. But if you need to do even a simple platfrom specific thing - let’s say to change windows title - there is no simple way. Things like <code class="language-plaintext highlighter-rouge">navigationBarItems</code> are tided to UIKit only plaftorm so that would force to switch to <code class="language-plaintext highlighter-rouge">Mac Catalyst</code>.</p>

<p>I’m eagier to find out what WWDC 2020 will bring - death of AppKit or more complex SwiftUI integration.</p>

<p>Anyway I was able to create simple tool to inspect frameworks to check it’s type and architecure. You can check it out in <a href="https://github.com/PycKamil/FrameworkInspector">Github</a>.</p>]]></content><author><name>Kamil Pyć</name></author><category term="programming" /><summary type="html"><![CDATA[WWDC is near by, is good to catch up with stuff that is had on my TODO list - SwiftUI. I was tempted to try it on Mac to see how it manages to hide all of the complexity of AppKit.]]></summary></entry><entry><title type="html">Lesson learned (again)</title><link href="https://pyckamil.github.io/programming/2020/05/06/lesson-learned(again).html" rel="alternate" type="text/html" title="Lesson learned (again)" /><published>2020-05-06T19:30:15+00:00</published><updated>2020-05-06T19:30:15+00:00</updated><id>https://pyckamil.github.io/programming/2020/05/06/lesson-learned(again)</id><content type="html" xml:base="https://pyckamil.github.io/programming/2020/05/06/lesson-learned(again).html"><![CDATA[<p>Even if you do proffesional programming for 10+ years you can think that easy <code class="language-plaintext highlighter-rouge">while</code> loop in bash is something simple. But it took 2 hours for me to figure out it’s opposite.</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"><span class="nv">array</span><span class="o">=()</span>

<span class="k">while </span>element
<span class="k">do
</span>array+<span class="o">=</span> element
<span class="k">done</span></code></pre></figure>

<p>In every case <code class="language-plaintext highlighter-rouge">array</code> was always empty. What? 🤨
Turnes out while loop is executed in different subshell and don’t have access to variable outside of it scope.</p>

<p>Solution: <strong>Switch to for loop</strong>.</p>]]></content><author><name>Kamil Pyć</name></author><category term="programming" /><summary type="html"><![CDATA[Even if you do proffesional programming for 10+ years you can think that easy while loop in bash is something simple. But it took 2 hours for me to figure out it’s opposite.]]></summary></entry><entry><title type="html">Welcome on my blog!</title><link href="https://pyckamil.github.io/general/2020/05/06/welcome-on-my-blog.html" rel="alternate" type="text/html" title="Welcome on my blog!" /><published>2020-05-06T16:30:15+00:00</published><updated>2020-05-06T16:30:15+00:00</updated><id>https://pyckamil.github.io/general/2020/05/06/welcome-on-my-blog</id><content type="html" xml:base="https://pyckamil.github.io/general/2020/05/06/welcome-on-my-blog.html"><![CDATA[<p>I never started blogging on something other than already set up Wordpress or other blogging platform since didn’t want to commit seriously in web development. This time I checked out something different - <a href="https://jekyllrb.com">Jekyll</a> - which is static site generator. It’s easy - took me about half on hour to start this site and it’s supported by Github pages so my investment was minimal 👌 Let’s see if I will have anythign interesing to share with iOS community 🤞</p>

<p>Check out the <a href="https://jekyllrb.com/docs/home">Jekyll docs</a> for more info on how to get the most out of Jekyll.</p>]]></content><author><name>Kamil Pyć</name></author><category term="general" /><summary type="html"><![CDATA[I never started blogging on something other than already set up Wordpress or other blogging platform since didn’t want to commit seriously in web development. This time I checked out something different - Jekyll - which is static site generator. It’s easy - took me about half on hour to start this site and it’s supported by Github pages so my investment was minimal 👌 Let’s see if I will have anythign interesing to share with iOS community 🤞]]></summary></entry></feed>