<?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>Forem: Omar Labib</title>
    <description>The latest articles on Forem by Omar Labib (@olabib).</description>
    <link>https://forem.com/olabib</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F739288%2F486c9404-eb18-4ec2-950b-e0db97cd70a9.jpg</url>
      <title>Forem: Omar Labib</title>
      <link>https://forem.com/olabib</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/olabib"/>
    <language>en</language>
    <item>
      <title>Advanced iOS development - Build Phases Part 2</title>
      <dc:creator>Omar Labib</dc:creator>
      <pubDate>Fri, 31 Dec 2021 18:53:28 +0000</pubDate>
      <link>https://forem.com/olabib/advanced-ios-development-build-phases-part-2-4hf7</link>
      <guid>https://forem.com/olabib/advanced-ios-development-build-phases-part-2-4hf7</guid>
      <description>&lt;p&gt;In part &lt;a href="https://dev.to/olabib/advanced-ios-development-build-phases-part-1-igk"&gt;one&lt;/a&gt;, we were introduced to how run scripts can be utilized as part of Xcode build process with a trivial example..&lt;/p&gt;

&lt;p&gt;In this post we will further demonstrate on run scripts but through very meaningful use case...&lt;/p&gt;

&lt;p&gt;If you've ever worked with localizable files in iOS, &lt;em&gt;I'm sure you have&lt;/em&gt;, You may have notice, &lt;em&gt;I'm not sure you may&lt;/em&gt;, that Xcode doesn't detect duplicated keys in the files, i.e. you can have multiple keys with different or even same values and Xcode won't complain about this..&lt;/p&gt;

&lt;p&gt;This of course is not a recommended practice at all, and must be avoided, and that's our duty in this post..&lt;/p&gt;

&lt;p&gt;Not only that, but we're going to highlight duplicated keys in Xcode as follows..&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wsEo0iVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9icr8tjma3iyxzsqnjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wsEo0iVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9icr8tjma3iyxzsqnjq.png" alt="Xcode error message" width="880" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Insert the following code inside into the code block in your run phase step, this code can be found &lt;a href="https://github.com/O-labib/Xcode-build-script-strings-duplications/blob/main/script"&gt;here&lt;/a&gt;..&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gCYwDrVS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6vysde2icof7jlls5ur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gCYwDrVS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6vysde2icof7jlls5ur.png" alt="Xcode" width="880" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's go over it line by line...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We find the &lt;code&gt;Localizable.strings&lt;/code&gt; files in the directory of the project, and iterate over them.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SRCROOT&lt;/code&gt; is an environment variable exposed by Xcode during the build process, thus &lt;code&gt;FILE_PATH&lt;/code&gt; represents the absolute path to the &lt;code&gt;Localizable.strings&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;We extract only the keys from the file.&lt;/li&gt;
&lt;li&gt;We filter the keys to the only duplicated ones.&lt;/li&gt;
&lt;li&gt;We iterate over the duplicated keys to get the key and its occurrences in the file.&lt;/li&gt;
&lt;li&gt;We iterate over these duplicated occurrences and get the line number then we print what key is duplicated and at which line.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The cool part is when it comes to highlighting this error message in Xcode..&lt;br&gt;
You just need to print the following message during the build process. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;echo "${filePath}:${lineNumber}:${columnNumber}: error: {errorMessage}"&lt;/code&gt;&lt;br&gt;
This highlights the message in Xcode as follows..&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wsEo0iVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9icr8tjma3iyxzsqnjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wsEo0iVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9icr8tjma3iyxzsqnjq.png" alt="Xcode error message" width="880" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If instead you want a warning instead of error in Xcode, you just need to change it to the following..&lt;br&gt;
&lt;code&gt;echo "${filePath}:${lineNumber}:${columnNumber}: warning: {errorMessage}"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This yields the following output..&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uQ-0kBlk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnrwr8vu6k9ic10ozx24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uQ-0kBlk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnrwr8vu6k9ic10ozx24.png" alt="Xcode warning message" width="880" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run scripts are such powerful features that can utilize to run any script you can think of... not only can you run shel scripts there, but you can run any sort of script, Your imagination is the limit 🚀&lt;/p&gt;

</description>
      <category>ios</category>
      <category>xcode</category>
      <category>swift</category>
    </item>
    <item>
      <title>Advanced iOS development - Build Phases Part 1</title>
      <dc:creator>Omar Labib</dc:creator>
      <pubDate>Sat, 25 Dec 2021 12:16:01 +0000</pubDate>
      <link>https://forem.com/olabib/advanced-ios-development-build-phases-part-1-igk</link>
      <guid>https://forem.com/olabib/advanced-ios-development-build-phases-part-1-igk</guid>
      <description>&lt;p&gt;Have you ever come across this build error in Xcode..&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5j5k09zer9bu4tlu9hyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5j5k09zer9bu4tlu9hyb.png" alt="Xcode build phase failure"&gt;&lt;/a&gt;&lt;br&gt;
I'm sure you have.&lt;br&gt;
During my first years of iOS development, this has been one of the most ambiauious errors for me, I can only see that I've messed up somewhere in the codebase and I have to go and see what I've done wrong, however, after I got to know build phases better in Xcode this couldn't make more sense..&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Phases
&lt;/h2&gt;

&lt;p&gt;In Xcode build phases section is the scope where Xcode offers you the possibility to run custom scripts &lt;em&gt;- known as run scripts -&lt;/em&gt; as part of the build process, these script can be tailored for any behavior you can think of. The cool thing though is that you can control the build process through this powerful script of you..&lt;br&gt;
Let's better have an example..&lt;/p&gt;

&lt;p&gt;For Starter, How can we add those run scripts? &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1fjxulghozxue8lhrfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1fjxulghozxue8lhrfa.png" alt="Xcode build phase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head to you project file.&lt;/li&gt;
&lt;li&gt;Choose your app target.&lt;/li&gt;
&lt;li&gt;Navigate the build phases tab.&lt;/li&gt;
&lt;li&gt;Click the + button and choose &lt;code&gt;New Run Script Phase&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will add a run script template for you..&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fffv0pyu9jzb5nj56h2hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fffv0pyu9jzb5nj56h2hw.png" alt="Xcode Run Script"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can give a cool name to your script.&lt;/li&gt;
&lt;li&gt;This is the path you shell on your machine.&lt;/li&gt;
&lt;li&gt;The Shell script that will be run during the building process.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Note: All these run scripts will run serially, and you can change the order by grabbing the run script and moving it up or down.&lt;/em&gt; &lt;br&gt;
For our very first run script, we will be doing something very simple..&lt;br&gt;
Just printing some message to the user..&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feou2x9ueij5gdtvkqh0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feou2x9ueij5gdtvkqh0z.png" alt="Xcode build phase"&gt;&lt;/a&gt;&lt;br&gt;
This message however won't be printed to the log. Instead, you can access it through the build report.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzrm5zuhifzyjgk78pjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzrm5zuhifzyjgk78pjq.png" alt="Xcode Build Report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the report navigator.&lt;/li&gt;
&lt;li&gt;Choose your build of interest.&lt;/li&gt;
&lt;li&gt;Choose all messages tab.&lt;/li&gt;
&lt;li&gt;You will find the message printed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let's tweak this build a little, let's break the build for no reason..&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fba3ucmg4icy9853s7aci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fba3ucmg4icy9853s7aci.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
The key here is to exit the script with any value rather than zero, this will indeed fail the script and all the succeeding run scripts won't even run.&lt;/p&gt;

&lt;p&gt;This will result in our friendly message we now understand its meaning.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxr5f2lc4zm5d2u15a7m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxr5f2lc4zm5d2u15a7m.png" alt="Xcode Build Phase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this is it for our first part, in the next part we will build upon our knowledge and develop a very useful run script to use in you apps, so stay tuned 😉&lt;/p&gt;

</description>
      <category>ios</category>
      <category>xcode</category>
      <category>swift</category>
    </item>
  </channel>
</rss>
