<?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: Luis Ramos</title>
    <description>The latest articles on DEV Community by Luis Ramos (@luisramos1337).</description>
    <link>https://dev.to/luisramos1337</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%2F262458%2Fac74c377-2433-467b-a557-cdb701e0d195.jpg</url>
      <title>DEV Community: Luis Ramos</title>
      <link>https://dev.to/luisramos1337</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luisramos1337"/>
    <language>en</language>
    <item>
      <title>Publishing your first android library!</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Tue, 15 Sep 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/publishing-your-first-android-library-576f</link>
      <guid>https://dev.to/luisramos1337/publishing-your-first-android-library-576f</guid>
      <description>&lt;p&gt;Publishing a library you develop is a journey on its own. It can be overwhelming, especially if you are targeting Android. There is a lot of documentation out here, but I could not find one that would go end to end with it. So I wrote this post!&lt;/p&gt;

&lt;p&gt;This came about because I released my first open source library: &lt;a href="https://github.com/orgmir/kroclin"&gt;Kroclin&lt;/a&gt;! It is a snapshot testing library written in Kotlin, to help out writing less code in your tests. Check it out and give it a star if would like. Now, let me tell you about the journey to release it!&lt;/p&gt;

&lt;p&gt;Sonatype provides a &lt;a href="https://dev.toossrh-guide"&gt;guide for OSS repository hosting&lt;/a&gt; and &lt;a href="https://dev.tooss-releasing"&gt;another one for releasing your deployment&lt;/a&gt; that I read, but they could be more helpful. Everything you need to know is there, it just takes several readings and lots of googling to grok it. Here are the steps you need to go through:&lt;/p&gt;

&lt;p&gt;First, &lt;a href="https://issues.sonatype.org/"&gt;create a Sonatype JIRA account&lt;/a&gt; if you don't have one already.&lt;/p&gt;

&lt;p&gt;Then &lt;a href="https://issues.sonatype.org/secure/CreateIssue.jspa?issuetype=21&amp;amp;pid=10134"&gt;create a new project issue&lt;/a&gt;. Make sure to click this link, since they require that you use the template. In the issue body, write that you want to claim the domain that matches the library &lt;code&gt;groupId&lt;/code&gt;. In the case of my library, the &lt;code&gt;groupId&lt;/code&gt; is &lt;code&gt;dev.luisramos.kroclin&lt;/code&gt; and I claimed &lt;code&gt;dev.luisramos.*&lt;/code&gt;. Here is &lt;a href="https://dev.tojira-ticket"&gt;my JIRA ticket&lt;/a&gt; as an example.&lt;/p&gt;

&lt;p&gt;I picked up from reading other issues that you only need to go through this process once, if you request a wildcard &lt;code&gt;groupId&lt;/code&gt;. Other libraries released under the same &lt;code&gt;groupId&lt;/code&gt; don't require a new project ticket to be created.&lt;/p&gt;

&lt;p&gt;Note that you could also claim the &lt;code&gt;groupId&lt;/code&gt; that matches your project hosting, for example, &lt;code&gt;io.github.orgmir&lt;/code&gt; if that's where your project lives.&lt;/p&gt;

&lt;p&gt;After you have opened a new project ticket, you need to prove that you own the domain you claimed. You can either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a TXT record to your DNS referencing the url to the JIRA ticket you created (fastest)&lt;/li&gt;
&lt;li&gt;Setup a redirect to your github page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I went with the first option, and since every DNS provider differs I won't go into specifics. Some googling on how to add a TXT record for your DNS provider should get you there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; You will need to submit the full URL for the issue, so in my case the content for the TXT record was &lt;a href="https://issues.sonatype.org/browse/OSSRH-60527"&gt;&lt;em&gt;https://issues.sonatype.org/browse/OSSRH-60527&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I went ahead and added a comment on the ticket with the output of &lt;code&gt;dig -t TXT luisramos.dev&lt;/code&gt;, just to show that it was working. Don't know if it made a difference 😅&lt;/p&gt;

&lt;p&gt;After doing the proof of domain ownership, you will need to wait for Sonatype to reply to your ticket. They will let you know once the repository on their end is ready to receive artifacts. Don't actually upload anything until they give you the OK, your artifacts will just end up in a generic catch-all repository.&lt;/p&gt;

&lt;p&gt;After they reply, go ahead and upload your first artifact. You can copy my &lt;a href="https://github.com/Orgmir/kroclin/blob/main/gradle/gradle-mvn-push.gradle"&gt;&lt;code&gt;gradle-mvn-push.gradle&lt;/code&gt;&lt;/a&gt; script and run &lt;code&gt;./gradlew clean build uploadArchives&lt;/code&gt; (don't worry, I also copied it from &lt;a href="https://github.com/JakeWharton/wormhole/blob/master/gradle/gradle-mvn-push.gradle"&gt;someone else&lt;/a&gt;). You could also use a plugin like &lt;a href="https://github.com/vanniktech/gradle-maven-publish-plugin"&gt;vanniktech/gradle-maven-publish-plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once the upload is done, go ahead and log in to &lt;a href="https://oss.sonatype.org"&gt;https://oss.sonatype.org&lt;/a&gt; using your Sonatype JIRA account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2N9bhsEV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://luisramos.dev/static/74473c8a088d2788f1013549e2f1e75f/c5bb3/nexus_repository_manager.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2N9bhsEV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://luisramos.dev/static/74473c8a088d2788f1013549e2f1e75f/c5bb3/nexus_repository_manager.png" alt="Nexus Repository Manager" title="Nexus Repository Manager"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;code&gt;Staging Repositories&lt;/code&gt; on the side bar, and you should see a list with the repository for your library. Select the repo, and press &lt;code&gt;Close&lt;/code&gt; on the top bar. This will perform some validation on Sonatype's side, and once the status updates and the repository is tagged as closed, select the repository again and press &lt;code&gt;Release&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you use a plugin, the upload step will probably try to close and release the staging repository. Loggin in to Nexus Repository Manager should only be needed when you are releasing for the first time, or if you use a script like me.&lt;/p&gt;

&lt;p&gt;You can now update on your JIRA ticket that the repository has been released. This will let Sonatype know, and they will trigger a sync with maven central, so your library can show when searching in &lt;a href="https://search.maven.org"&gt;search.maven.org&lt;/a&gt;. This step should is also only needed the first time you are releasing.&lt;/p&gt;

&lt;p&gt;And that's it! It might take a couple of hours for the sync to happen, but congratulations! You have released a library onto the world! What a trip it was 🚀&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Ler - An RSS Aggregator for Android!</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Fri, 20 Mar 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/ler-an-rss-aggregator-for-android-61p</link>
      <guid>https://dev.to/luisramos1337/ler-an-rss-aggregator-for-android-61p</guid>
      <description>&lt;p&gt;I have been working on a RSS aggregator app called &lt;em&gt;Ler&lt;/em&gt;. Its available for Android, and you should &lt;a href="https://play.google.com/store/apps/details?id=app.luisramos.ler"&gt;give it a try!&lt;/a&gt; It is the first app I design, develop and publish all by myself, so I am pretty proud of that!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=app.luisramos.ler"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aKlCNTqU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" alt="Get it on Google Play"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I know what you are thinking, &lt;em&gt;another&lt;/em&gt; RSS feed app? Aren't there billions of them? Well, yes. But this one is mine. And I have plans. Big plans! Let me tell you how it came to be, and what I want to do with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Twitter is a time sink
&lt;/h3&gt;

&lt;p&gt;I spend too much time on twitter. I checked my phone usage settings for apps, and twitter is always number one on the list, toppling YouTube (!!) and WhatsApp. I though I watched a lot of Youtube, but aparently, on a very boring day, I accumulated &lt;em&gt;4 hours&lt;/em&gt; of twitter usage...&lt;/p&gt;

&lt;p&gt;So I looked into Googles digital wellbeing app, and turned on a 30 minute timeout for Twitter. And it works! Some days, I don't even reach the timeout. Unfortunatly, this also meant that a lot of the blogs I read wouldn't reach me as well.&lt;/p&gt;

&lt;p&gt;And there you have it. I took the time I was wasting and built this app!&lt;/p&gt;

&lt;h3&gt;
  
  
  Ler
&lt;/h3&gt;

&lt;p&gt;The app name is the portuguese word for &lt;em&gt;reading&lt;/em&gt;. I did a search and it seems nobody claimed it, so why not? The main features that I have built so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can subscribe to RSS feeds (crazy I know). You can manually type in a website adress, or you can share from the browser to the app!&lt;/li&gt;
&lt;li&gt;You can filter out articles that you already read, or just show articles from one feed.&lt;/li&gt;
&lt;li&gt;You can swipe an article to toggle it read, or mark all articles in a feed at once!&lt;/li&gt;
&lt;li&gt;Feeds will be checked for updates every hour automagically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Articles currently open in the browser. I toyed with the idea of having a built in reader, but that seemed overkill for what I wanted to do. I already used the browser to do most of my reading anyway.&lt;/p&gt;

&lt;p&gt;I am pretty proud of how it turned out, despite not being great at UI design, I kept it simple and it does the job! I have been using it for the past couple of weeks, and I think I impressed myself by actually using it instead of defaulting to Twitter as a time killer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open so everyone can &lt;em&gt;read&lt;/em&gt; it
&lt;/h3&gt;

&lt;p&gt;Not only am I using this app to avoid using twitter all the time, I will also use it as a showcase project. Hence, my plan in the next weeks is to write a bunch of tests, clean up the folder structure, and open source it.&lt;/p&gt;

&lt;p&gt;So far, I have not worked in an app that had their source open, so most often when talking about my work I can't provide examples. I applied all my knowledge and tried to build the simples app I could, while still being a good example of how I would build an app.&lt;/p&gt;

&lt;p&gt;My plan is to also write about android development, while using the app as an example. I made some architecture choices that I can talk about, since I haven't found a lot of written examples online.&lt;/p&gt;

&lt;p&gt;Please give it a spin, and let me know what you think! You can &lt;a href="https://twitter.com/luisramos1337"&gt;tweet at me&lt;/a&gt; or send me an &lt;a href="//mailto:luis.ramos@hey.com?subject=Ler%20Feedback"&gt;email&lt;/a&gt;. I have a little roadmap with more features, but let me know if you want a particular feature added, and I will add it to the list!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My new blog! - Creating a Gatsby website</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Tue, 17 Mar 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/my-new-blog-creating-a-gatsby-website-1il3</link>
      <guid>https://dev.to/luisramos1337/my-new-blog-creating-a-gatsby-website-1il3</guid>
      <description>&lt;p&gt;Welcome to my new blog! Hope you enjoy it, I have spent the last couple of weeks building it. Now that it is done, I can finally start writing about stuff!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I kinda rebuilt it because I wanted to write about building it...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So let me tell you how it works, what I learned, and how easy it is to do it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;

&lt;p&gt;To be upfront about it, this blog is built using &lt;a href="https://www.gatsbyjs.org/"&gt;Gatsby&lt;/a&gt;, and deployed using Github Actions to a Digital Ocean droplet. And I am very happy with it. This entire website is open source, so if you wanna check the code &lt;a href="https://github.com/orgmir/luisramos.dev"&gt;go ahead&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;One day I was reading some blog posts from Tania Rascia and &lt;a href="https://www.taniarascia.com/migrating-from-wordpress-to-gatsby/"&gt;this post&lt;/a&gt; made me look into Gatsby. In it she migrated her wordpress blog to a Gatsby website that she built from a pretty bare bones template. I have been thinking of revamping my blog again, since the last one was &lt;a href="https://dev.to/migration-to-hugo/"&gt;more than a year ago&lt;/a&gt;. Pairing that with my interest with this new JAMStack thing, I just got excited and started looking through the docs!&lt;/p&gt;

&lt;p&gt;After building this website, I really enjoyed working with the plugin system and I loved that it used React and Graphql.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;Following Tania's footsteps, I installed the &lt;code&gt;gatsby-cli&lt;/code&gt; and created a website using the &lt;a href="https://github.com/vagr9k/gatsby-advanced-starter/"&gt;gatsby-advanced-starter&lt;/a&gt;. Turns out, that was totally overkill for me, and most of the things there overwhelmed me. So I tried again running &lt;code&gt;gatsby new luisramos.dev&lt;/code&gt; and slowly added the plugins I needed as I went along.&lt;/p&gt;

&lt;p&gt;Starting with the empty project, the first thing I did was setup &lt;a href="//tailwindcss.com/"&gt;Tailwind CSS&lt;/a&gt;. I am not very good in terms of design skills, and playing around with CSS is fun but can also become a huge waste of time. Tailwind fits nicelly into the "just make a component" React world, and paired with a fantastic documentation page, it is very easy to work with. You can quickly create your styles using the existing classes, and when it you start duplicating a lot, you move everything to a component! 👍&lt;/p&gt;

&lt;p&gt;Setting up Tailwind with Gatsby was as easy as adding the plugin &lt;code&gt;gatsby-plugin-postcss&lt;/code&gt; to gatsby configuration, adding a &lt;code&gt;postcss.config.js&lt;/code&gt; requiring the Tailwind library, and adding the Tailwind css imports to the &lt;code&gt;global.css&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;I am very impressed with the plugin system. Anything you need, and you bet there is a plugin that does it! I wanted a RSS feed with all my posts, there's a plugin for that: &lt;code&gt;gatsby-plugin-feed&lt;/code&gt;. I want my posts to be in markdown, there's a plugin for that: &lt;code&gt;gatsby-transformer-remark&lt;/code&gt;. I wanted syntax highlighting for my code snippets, there's even a plugin for the plugin: &lt;code&gt;gatsby-remark-prismjs&lt;/code&gt;! Overall, very wonderful to work with.&lt;/p&gt;

&lt;p&gt;This plugin system even got me wanting to build more websites!&lt;/p&gt;

&lt;h3&gt;
  
  
  React+Graphql
&lt;/h3&gt;

&lt;p&gt;Another feature I enjoyed was the React and Graphql support. In the beggining it felt very overkill to have a graphql query everywhere, but the more I read the documentation, the more it made sense to me.&lt;/p&gt;

&lt;p&gt;I have enough experience with React that I could jump straight into this new website building my layout. After I had build the header/footer/nav combo, I started thinking about the main page, and I decided that I wanted the latest three posts there. So when you land, you can immediatly read some stuff.&lt;/p&gt;

&lt;p&gt;To do this, you write a graphql query in your React page, name it &lt;code&gt;pageQuery&lt;/code&gt; and export it. Then, Gatsby will take the data generated from that query and feed it to the component.&lt;/p&gt;

&lt;p&gt;The whole experience around this was incredible: I played around with the graphql browser until I had the data I wanted, I pasted the query into the page component, and like magic the data was there! Graphql is pretty sweet.&lt;/p&gt;

&lt;p&gt;After that, I added some code to &lt;code&gt;gatsby-node.js&lt;/code&gt; so it would create a page for all of my posts. It uses a template, so I don't need to create a component for each post manually. After that, I added a contact and about pages, an RSS feed, some more styling and a bit of content. Sooner than I was expecting, I had a website ready to be deployed!&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment via Github Actions
&lt;/h2&gt;

&lt;p&gt;My previous blog was hosted on the same &lt;a href="%5Bhttps://www.digitalocean.com%5D(https://www.digitalocean.com/)"&gt;Digital Ocean&lt;/a&gt; droplet that this one is. I have this one box that I use to play around with several things, so since I am already paying for it, and I don't drive a lot of traffic, I planned the same for this blog.&lt;/p&gt;

&lt;p&gt;The deployment steps to get this into the server are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;gatsby build&lt;/code&gt; to get the static version of the website&lt;/li&gt;
&lt;li&gt;Upload the generated folder to the server, preferebly using &lt;code&gt;rsync&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I shopped around a bit, and I am impressed by the amount of Github actions already available. I created a workflow that checkouts my code, runs the build and uploads the website to my server in less than half an hour. And it caches the &lt;code&gt;~/.npm&lt;/code&gt; folder, so it all runs in 2 mins on CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yay Gatsby
&lt;/h2&gt;

&lt;p&gt;I am very happy with the current setup. This website already has pulled this post out of me, so lets see if it makes me write more! Hope you enjoyed this write up as much as I have enjoyed building the site.&lt;/p&gt;

&lt;p&gt;If you liked this post, or if you just wanna send me some feedback, send me a &lt;a href="https://twitter.com/luisramos1337"&gt;tweet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a final note, I wrote this post in a very cool markdown editor, &lt;a href="https://typora.io/"&gt;Typora&lt;/a&gt;. It is free during beta, so give it a try!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Oh My Zsh prompt theme for Windows Powershell!</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Sat, 04 May 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/oh-my-zsh-prompt-theme-for-windows-powershell-43fl</link>
      <guid>https://dev.to/luisramos1337/oh-my-zsh-prompt-theme-for-windows-powershell-43fl</guid>
      <description>&lt;p&gt;I do most of my programming in my mac these days, but once in a while my gaming desktop becomes the testground for some code bashing. Since I use git on the terminal, on windows I use powershell instead of a sweet zsh shell.&lt;/p&gt;

&lt;p&gt;Working with powershell is not that bad, but I terribly miss not having the git branches on my prompt. Since I really enjoy the &lt;a href="https://ohmyz.sh/"&gt;Oh My Zsh&lt;/a&gt; theme on my Mac, here’s a snippet that changes your power shell prompt!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function prompt {
\$ESC = [char]27

$p = Split-Path -leaf -path (Get-Location)
  $branch = $(git symbolic-ref -q HEAD) -replace "refs/heads/"
  if ($branch) {
$branch = "$ESC[34mgit:($ESC[0m$ESC[31m$branch$ESC[0m$ESC[34m)$ESC[0m "
}

"$ESC[1m$ESC[32m$([char]0x279C)$ESC[0m $ESC[36m$p$ESC[0m $branch\$ESC[0m"
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This code lands in the &lt;code&gt;$profile&lt;/code&gt; file, which probably needs to be created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new-item -itemtype file -path $profile -force
notepad $PROFILE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notepad should open up and you can copy paste the snipped there!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Auto Layout UIView Extension: A quick way to programatically create layouts</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Tue, 30 Apr 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/auto-layout-uiview-extension-a-quick-way-to-programatically-create-layouts-57c6</link>
      <guid>https://dev.to/luisramos1337/auto-layout-uiview-extension-a-quick-way-to-programatically-create-layouts-57c6</guid>
      <description>&lt;p&gt;Recently I have taken a renewed interest into this blog. I have revamped the theme (mostly stealing it from my friend's blog, &lt;a href="https://accidental.dev/"&gt;check it out&lt;/a&gt;) and now I'm focusing on writing more regularly. I noticed that a lot of my code snippets are just sitting quietly on Github or Gitlab and could use a post or two to describe why I made them!&lt;/p&gt;

&lt;p&gt;The first one I want to talk about is a UIView extension that I always use in my iOS projects. I always prefer to build my interface programatically, so that lead me to search for a few auto layout libraries.&lt;/p&gt;

&lt;p&gt;The issue I have with using an auto layout library is that if a new developer joins the team, that person will need to deal with my choice of library that usually comes with its own set of idioms and abstractions. My experience is that people enjoy building layouts differently and the preference will always be for some other library! Also, the added abstractions leave me a bit too far away from the auto layout specifics.&lt;/p&gt;

&lt;p&gt;Instead of choosing a library, a few years ago I created an extension with just a couple of methods to see if I could get away without adding a dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func align(with view:UIView, constant:CGFloat = 0.0) {
  translatesAutoresizingMaskIntoConstraints = false
  leftAnchor.constraint(equalTo: view.leftAnchor, constant: constant).isActive = true
  rightAnchor.constraint(equalTo: view.rightAnchor, constant: -constant).isActive = true
  topAnchor.constraint(equalTo: view.topAnchor, constant: constant).isActive = true
  bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -constant).isActive = true
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I kept adding to it as I needed and it kept growing. Currently it looks more like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@discardableResult
func align(with view: UIView, constant: CGFloat = 0.0) -&amp;gt; [NSLayoutConstraint] {
  translatesAutoresizingMaskIntoConstraints = false
  let constraints = [
    leftAnchor.constraint(equalTo: view.leftAnchor, constant: constant),
    rightAnchor.constraint(equalTo: view.rightAnchor, constant: -constant),
    topAnchor.constraint(equalTo: view.topAnchor, constant: constant),
    bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -constant),
  ]
  NSLayoutConstraint.activate(constraints)
  return constraints
}

@discardableResult
func alignTop(to anchor: NSLayoutYAxisAnchor, constant: CGFloat = 0.0, priority: UILayoutPriority = .required, isActive: Bool = true) -&amp;gt; NSLayoutConstraint {
  translatesAutoresizingMaskIntoConstraints = false
  let constraint = topAnchor.constraint(equalTo: anchor, constant: constant)
  constraint.priority = priority
  constraint.isActive = isActive
  return constraint
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, some wrapper functions with sensible defaults make auto layout better to work with. The code becomes cleaner and easier to read, and you don't loose any of the features that auto layout gives us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func viewDidLoad() {
  super.viewDidLoad()
  // ... setup view code

  containerView.align(with: view)
  textView.alignTop(with: view, constant: 40)
  textView.alignLeadingTrailing(with: view, constant: 20)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This extension has grown after several years of copying this over to each new project and adding something that was missing. It fits my needs well, so I have stopped looking for an auto layout library! The full extension is available &lt;a href="https://gist.github.com/Orgmir/a140b15c1f2ab86b2a72d4c09570cd52"&gt;in this public gist.&lt;/a&gt; Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Blog revamp: Migrating to Hugo</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Thu, 27 Sep 2018 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/blog-revamp-migrating-to-hugo-24kc</link>
      <guid>https://dev.to/luisramos1337/blog-revamp-migrating-to-hugo-24kc</guid>
      <description>&lt;p&gt;_ &lt;strong&gt;Update:&lt;/strong&gt; _ Since this post was made, I have moved my blog to a new website and tech stack. Check out the post about the new &lt;a href="https://luisramos.dev/new-blog-creating-gatsby-website"&gt;revamp&lt;/a&gt;!&lt;/p&gt;




&lt;p&gt;The blog has a new look! I like to think it looks a bit better now. Of course the fun side of it is the tech stack. It is now generated using &lt;a href="http://gohugo.io/"&gt;hugo&lt;/a&gt;, deployed using &lt;a href="http://gitlab.com/"&gt;Gitlab&lt;/a&gt; incredible CI pipelines, and also I'm hosting it on a &lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt; droplet.&lt;/p&gt;

&lt;p&gt;I want to talk about my experience migrating from Jekyll to hugo, and how I went about setting everything up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating to Hugo
&lt;/h2&gt;

&lt;p&gt;This blog was previously hosted in Github pages, and it used Jekyll to render the static pages. All the content was in markdown already, so it was relatively easy to migrate it to hugo. The content structure is relatively similar in both frameworks. I only had trouble with the syntax higlight for my code snippets, and with processing the template sass files to css.&lt;/p&gt;

&lt;p&gt;Hugo uses a code syntax generator called &lt;a href="https://github.com/alecthomas/chroma"&gt;Chroma&lt;/a&gt;. The only change is that instead of using the normal markdown code marks, it uses specific tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt; highlight swift &amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You also need to declare the language you are highlighting (&lt;code&gt;swift&lt;/code&gt; in that example).&lt;/p&gt;

&lt;p&gt;Generating new content is super easy and fast, you just run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hugo new posts/title-of-blog-post.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will create a new file in the specified content folder, with some front-matter meta data already setup for you to fill.&lt;/p&gt;

&lt;p&gt;The template system is also straighforward to use, and you can easily define new content types and front-matter, to be used by the &lt;code&gt;hugo new&lt;/code&gt; command.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hugo Extended
&lt;/h3&gt;

&lt;p&gt;I found a gap in documentation about this, but it seems that hugo has an "extended" version. It adds extras, like sass processing, to the usual binary.&lt;/p&gt;

&lt;p&gt;When I tried to edit the template sass files, the changes weren't visible on refresh. They were being ignored, and since I was running locally there was no change it could be some cache issue.I eventually figured out that the template was using generated resources in a &lt;code&gt;resources/_gen/&lt;/code&gt; folder, and deleting that basically broke the generation. Since no css was found, hugo errored out and didn't generate the website.&lt;/p&gt;

&lt;p&gt;After googling around, I found out about the extended version of hugo that you can download from their releases page. Running the extended version compiled the sass files into css, and made everything work again. But now this means I need the extended version to generate my website, since I want to process the sass files on every generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment with Gitlab CI
&lt;/h2&gt;

&lt;p&gt;If you haven't tried &lt;a href="http://gitlab.com/"&gt;Gitlab&lt;/a&gt; you should really give it a spin. I'll to not fanboy about it too much, but they have some amazing features.&lt;/p&gt;

&lt;p&gt;One of them is the ability to setup a CI pipeline, writing some configuration on a &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; at the root of your repo. This way, everytime I push a commit to master, a deployment is triggered by Gitlab.You get 1000 free minutes of running time each month, more than enough for all your blogging needs.&lt;/p&gt;

&lt;p&gt;Since I have to use hugo extended to generate my website, I couldn't use the suggested image to run my build. I created a new Dockerfile that installs the right hugo binary, and also all the commands needed for deployment. This highlights another cool feature of Gitlab: you have a container register for each project, meaning you can have your container images right next to the project they are relevant to.&lt;/p&gt;

&lt;p&gt;After I built and pushed the image, I just needed to reference it in my CI file to get it running the deployment without a hitch! It's pretty satisfying to finally get a CI job green. Check out the &lt;a href="https://gitlab.com/snippets/1757791"&gt;&lt;code&gt;.gitlab-ci.yml&lt;/code&gt;&lt;/a&gt; and the &lt;a href="https://gitlab.com/snippets/1757792"&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/a&gt; used for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting on Digital Ocean
&lt;/h2&gt;

&lt;p&gt;The final command of the deployment is a rsync into a Digital Ocean droplet. Pretty satisfied with the setup process for creating a droplet, it's a one button click for most of what you need. Haven't had an issue with it yet!&lt;/p&gt;

&lt;p&gt;I am using nginx to serve the website on the droplet, which was fairly easy to setup with all the info that is available online. I setup certbot to create and automatically renew ssl certificates for the website. It also takes care of updating the website config for you.&lt;/p&gt;

&lt;p&gt;Also, since Cloudflare has a one website free tier, I got all of my traffic running through it. So hopefully, my droplet will barelly be touched!&lt;/p&gt;

&lt;h2&gt;
  
  
  DevOps for the common man
&lt;/h2&gt;

&lt;p&gt;I am really happy with this setup. Hugo is a powerful framework, quick to setup but roboust enough to handle more heavy duty websites. Gitlab enables DevOps for the common man, giving me control over it but in a way that I'm not overwhelmed. And hosting solutions like Digital Ocean used in conjuction with CDNs like Cloudflare mean that you can serve a lot of people for cheap. A lot can be done by leveraging this infrastructure, which gets me excited!&lt;/p&gt;

&lt;p&gt;Next up, I'll add a static CMS like &lt;a href="https://www.netlifycms.org/"&gt;Netlify&lt;/a&gt; to this blog so I can write from anywhere!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>iOS local notifications ninja bug!</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Tue, 26 Sep 2017 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/ios-local-notifications-ninja-bug-1bee</link>
      <guid>https://dev.to/luisramos1337/ios-local-notifications-ninja-bug-1bee</guid>
      <description>&lt;p&gt;Recently I was working in a project that require me to show a local notification. And for the love of XCode, the app would not show an alert! I was at a loss!&lt;/p&gt;

&lt;p&gt;Beggining with iOS 10, the iOS notification framework was revamped to unify both remote and local notifications. This threw me into a loop while trying to figure out the problem. The only thing I had to go by was an error message that poped up when adding the notification to UNUserNotificationCenter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Adding notification request failed with error: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.usernotifications.usernotificationservice" UserInfo={NSDebugDescription=connection to service named com.apple.usernotifications.usernotificationservice}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What a cryptic message, thanks Apple Dev team! I had a custom action setup, so the user could open a url with more info. I was adding this URL to the &lt;code&gt;userInfo&lt;/code&gt; of the notification and here was where the bug lived! The issue was that I was adding the URL object, instead of an absolute string of the url. As soon as I changed this, everything worked.&lt;/p&gt;

&lt;p&gt;Of course, a &lt;a href="https://stackoverflow.com/questions/41360531/unmutablenotificationcontent-with-custom-object-in-userinfo"&gt;stackoverflow answer&lt;/a&gt; helped me figure this out!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Fastlane Supply uploads everything!</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Tue, 05 Sep 2017 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/fastlane-supply-uploads-everything-2nc4</link>
      <guid>https://dev.to/luisramos1337/fastlane-supply-uploads-everything-2nc4</guid>
      <description>&lt;p&gt;Ever since I found out about &lt;a href="https://fastlane.tools/"&gt;&lt;code&gt;fastlane&lt;/code&gt;&lt;/a&gt;, I've been using it to deploy Android and iOS apps. It's amazing how streamlined things can get: it saves you a bunch of time when deploying a release; it supports integrations with your favourite distribution platforms (yay Crashlytics); and you can easily copy the setup from one app to the other! Couldn't be happier with it.&lt;/p&gt;

&lt;p&gt;Here's a tip for the Android devs out there using &lt;a href="https://fastlane.tools/"&gt;&lt;code&gt;fastlane&lt;/code&gt;&lt;/a&gt;, add this to your &lt;code&gt;before_all&lt;/code&gt; step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;before *all do
  sh "rm -f ../app/build/outputs/apk/*/\_/\*.apk"
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I've found that when deploying Android builds using &lt;code&gt;supply&lt;/code&gt;, the tool tries to upload whatever it can find in your &lt;code&gt;build/outputs&lt;/code&gt; folder. And often the error you get are unrelated like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Google Api Error: apkUpgradeVersionConflict:
APK specifies a version code that has already been used.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is obviously not true if you check your google play console and your build.gradle file. Looking at the output the (at the &lt;code&gt;GRADLE_ALL_APK_OUTPUT_PATHS&lt;/code&gt; variable), it seems supply is trying to upload every apk he finds, including debugging version and other flavors. Adding that line will save you some time and stop you from screaming "Why don't the versions match??"&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Xcode crash on auto-complete: Snippets!</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Sun, 07 Feb 2016 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/xcode-crash-on-auto-complete-snippets-46f1</link>
      <guid>https://dev.to/luisramos1337/xcode-crash-on-auto-complete-snippets-46f1</guid>
      <description>&lt;p&gt;My XCode crashed after updating it to version 7.2. It happened everytime I tried to use auto-complete in an Obj-c file. Since my project was in Swift, it didn't bother me much. Things got worse when I actually needed to edit some library code!&lt;/p&gt;

&lt;p&gt;It crash with this exception:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(NSInvalidArgumentException): -[__NSCFData isEqualToString:]: unrecognized selector sent to instance 0x7fd01c5d4530
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since I got bored fast using a text editor to work around it, I tried to fix it. I use some plugins, one of them being &lt;a href="https://github.com/FuzzyAutocomplete/FuzzyAutocompletePlugin"&gt;fuzzy-autocomplete&lt;/a&gt; (if you don't use it, check it out, it's awesome!) I assumed the problem was with one of them. I removed them one by one and everytime I tried, BAM! Still crashing!&lt;/p&gt;

&lt;p&gt;This was bad, because plugins where my only option. After googling for a while, I didn't find anyone with a similar problem, so I guessed it had something to do with my custom instalation. And this is dumb, but I should have looked to the XCode crash log sooner...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;6 0x00000001038f4708 +[IDECodeSnippetLibraryCompletionStrategy_scope:matchesScope:atBOL:] (in IDEKit)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After checking the crash log, it was apparent who the culprit was: Snippets!&lt;/p&gt;

&lt;p&gt;It was the only custom thing left on my instalation. I renamed the snippets folder, effectivly stoping XCode from finding them. And guess what? Yes! Auto-complete worked again! I re-added all my loved plugins (fuzzy-autocomplete included), and back to coding I was. I dind't add my snippets, because I wasn't using them at all. But recreating them with the new XCode should solve the problem.&lt;/p&gt;

&lt;p&gt;Just another day working with XCode...&lt;/p&gt;

&lt;p&gt;PS: On a side note, if you don't use plugins with XCode, check &lt;a href="http://alcatraz.io/"&gt;Alcatraz&lt;/a&gt;, a plugin manager! You are bound to find something that will improve your XCode usage :)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>iOS Project Structure</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Mon, 11 Jan 2016 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/ios-project-structure-1obm</link>
      <guid>https://dev.to/luisramos1337/ios-project-structure-1obm</guid>
      <description>&lt;p&gt;To better organized my code, I have been changing my project structure along the years. I think I've finally set with one, so time to record it for the future!&lt;/p&gt;

&lt;p&gt;There are two basic guidelines when creating a project structure. First, keep it simple. Second, use something that makes sense to you.&lt;/p&gt;

&lt;p&gt;If you google a bit for this topic you may find this quora &lt;a href="https://www.quora.com/How-should-I-structure-my-iOS-app"&gt;answer&lt;/a&gt; or these &lt;a href="https://github.com/futurice/ios-good-practices#project-structure"&gt;guidelines&lt;/a&gt;. They both suggest something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View Controllers&lt;/li&gt;
&lt;li&gt;Views&lt;/li&gt;
&lt;li&gt;View Models&lt;/li&gt;
&lt;li&gt;UI (aka storyboards)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have small projects, this structure will work fine. But when you start adding more files to it it becomes confusing. I rather organize files in a functional way, separating them by areas and layers of the app. So it ends up something more like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interface&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base&lt;/li&gt;
&lt;li&gt;Onboarding&lt;/li&gt;
&lt;li&gt;Feed&lt;/li&gt;
&lt;li&gt;User&lt;/li&gt;
&lt;li&gt;Settings

&lt;ul&gt;
&lt;li&gt;Networking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Local Storage
&lt;/h2&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Classes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Categories/Extensions&lt;/li&gt;
&lt;li&gt;Classes that don't fit anywhere else

&lt;ul&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside those folders I usually follow the first setup, separating files by Views, ViewControllers, etc. This way you have almost every file related to an area of the app in one folder. All my images are stored in XCAssets. Fonts and other raw files are in Resources (usually with a dedicated folder for each).&lt;/p&gt;

&lt;p&gt;If you have an even awesome setup or if you just want to share yours, feel free to &lt;a href="https://twitter.com/luisramos1337"&gt;send me a tweet&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Swift Variables in Extensions</title>
      <dc:creator>Luis Ramos</dc:creator>
      <pubDate>Mon, 19 Oct 2015 00:00:00 +0000</pubDate>
      <link>https://dev.to/luisramos1337/swift-variables-in-extensions-j0j</link>
      <guid>https://dev.to/luisramos1337/swift-variables-in-extensions-j0j</guid>
      <description>&lt;p&gt;I have recently started working on a project that uses Swift2.0! I have been using Obj-C for the past 3 years, and when Swift came I wasn't one of the early adopters. Problems with the language and with SourceKit always crashing in XCode 6 didn't make for a good dev enviroment. Now with the 2.0 released to the wild, the promisse of open source and XCode 7, Swift is good to go!&lt;/p&gt;

&lt;p&gt;One of the first problems I had is one that happens to many iOS developers that use extensions/categories in their projects: How do I add a variable (static or not) to an extension?&lt;/p&gt;

&lt;p&gt;Since I seem to always be googling for this one, I'll log it here for future convinience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static Variables
&lt;/h3&gt;

&lt;p&gt;For a static variable, there is actually a really neat way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extension UIView {
  struct Static {
    static var defaultPadding : CGFloat = 16
  }
  func widthWithPadding() -&amp;gt; CGFloat {
    return self.bounds.width + Static.defaultPadding
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since you can declare structs in an extension, you can use these value objects to hold your static variables and they function the same way as declaring a static variable on the class. If you don't like the extra &lt;code&gt;Static.&lt;/code&gt; declaration, you can create wrappers using computed variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extension UIView {
  var defaultPadding : CGFloat { return Static.defaultPadding }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Instance Variables
&lt;/h3&gt;

&lt;p&gt;For instance variables the solution is to use the obj-c runtime. You need to create computed variables that get and set an associated object using &lt;code&gt;objc_getAssociatedObject()&lt;/code&gt; and &lt;code&gt;objc_setAssociatedObject()&lt;/code&gt;. This is the same approach taken if using it with Obj-C.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import ObjectiveC

extension UIViewController {
  struct Static {
    static var MainTitle = "\_MainTitle"
  }
  var mainTitle: String? {
    get{
      return objc_getAssociatedObject(self,&amp;amp;Static.MainTitle) as? String
    }
    set(value){
      if newValue = newValue {
        objc_setAssociatedObject(self,&amp;amp;Static.GenericTitle,newValue as NSString?,.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That way you can extend to your heart desire! If you want to understand the difference between structs and classes check out the &lt;a href="https://dev.toappledocs-class-vs-strutc"&gt;Apple docs&lt;/a&gt;. And to find out more about what kind of magic you can do with obj-c runtime check out &lt;a href="https://dev.tonshipster-objc"&gt;NSHipster post on it&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
