<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by César Vargas Casaseca on Medium]]></title>
        <description><![CDATA[Stories by César Vargas Casaseca on Medium]]></description>
        <link>https://medium.com/@toupper?source=rss-c2f877dba4d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*nrIbxPBpbhMSfi0yXuBkDA@2x.jpeg</url>
            <title>Stories by César Vargas Casaseca on Medium</title>
            <link>https://medium.com/@toupper?source=rss-c2f877dba4d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 03 Aug 2026 13:16:00 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@toupper/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Convert Swift Facades Into async/await Syntax With Continuations]]></title>
            <link>https://medium.com/better-programming/convert-your-swift-facades-to-the-new-async-await-syntax-using-continuations-d4a7bda4611b?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/d4a7bda4611b</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Mon, 27 Dec 2021 16:06:50 GMT</pubDate>
            <atom:updated>2022-01-12T16:48:38.930Z</atom:updated>
            <content:encoded><![CDATA[<h4>Leverage the power of Continuations when converting callbacks or delegate based APIs</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d7rI2CKxDkIfcMDmn4IReg.png" /><figcaption>Souce: <a href="https://undraw.co/">Undraw</a></figcaption></figure><p>The new async/await Swift concurrency API released together with Swift 5.5 was finally unveiled during the WWDC 21 last June. This new architecture fulfilled all the expectations that we iOS developers had, who were eagerly waiting for this since the Swift first release in 2014, and whose hopes got boosted in 2017 with the <a href="https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782#part-1-asyncawait-beautiful-asynchronous-apis">Swift Concurrency Manifesto</a> by Chris Lattner himself.</p><p>From all the new APIs and tools that were introduced, the new async/await syntax, Actors, and Tasks attracted most of the attention from the Swift community. And rightly so, these new additions improved considerably the readability of asynchronous code and the easiness when ensuring thread safety in our apps.</p><p>However, there was another mechanism introduced then that didn’t capture so much consideration even though they are very powerful when working together with async/await: Continuations.</p><h3>What are Continuations?</h3><p>According to the <a href="https://developer.apple.com/documentation/swift/checkedcontinuation">documentation</a>, Continuations are a mechanism to interface between synchronous and asynchronous code, logging correctness violations.</p><p>More precisely, a Continuation is an object that captures the program state at a given point, being able to continue it when it is required.</p><p>This might still sound very abstract, but we can learn to appreciate it deeper when considering how Apple implements asynchronous code up until now, with callbacks and the delegate pattern.</p><p>Continuations shine with all their brightness when working with these two patterns: they act as a bridge between the old world (callbacks and delegates) and the new one (async/await to achieve a more readable and structured code) by helping to create new async functions facading the old ones.</p><p>This is helpful when facading third party libraries or Apple APIs containing these patterns, as in the case that we will see today.</p><h3>Facading a delegate Based class with Continuations</h3><p>In our iOS team, we like to facade some Apple or third party developers components with our own ones. The purpose of this pattern is manyfold, but three points really stand out for us:</p><ul><li>We improve the readability and usability of that component with an easier API that hides the details of a more complex one</li><li>We make it easier to mock and thus improve testability in our code</li><li>Being more loosely coupled makes it easy to replace that facaded component in case we want to use a new technology</li></ul><p>Take for instance our LocationManager class. As pointed before, we want to simplify and hide the complexity of Apple’s CLLocationManager, that is implemented through the delegation pattern via the CLLocationManagerDelegate protocol.</p><p>To be simpler, we obtain the user location at a given moment just once, without the need to keep listening to location changes.</p><p>In spite of this, we do not hold anything against the delegate pattern per se; we take it as another powerful tool in our toolset that might be very useful for the right case.</p><p>Coming back to our case, it is essential to remark that because we need the location just once (fire and forget), we can convert our API to async/await, same way as before we used promises.</p><p>If it was required to be updated on any of the user location changes we would still have to use some sort of reactive programming paradigm as Combine or RxSwift, because there is a continuous flow to observe.</p><h3>Swift Concurrency Evolution</h3><p>The git history of the LocationManager file is a very interesting source to track the evolution of concurrency in Swift and our team.</p><p>After a brief period of using the raw Delegate Apple API, we started facading it by using callbacks, passing the new location to the client through a closure.</p><p>After that we discovered the power of Promises and created our own light Promises Open Source library to implement them, <a href="https://github.com/spring-media/PiedPiper">Pied Piper</a>. (Again, if there was the need of being updated continuously we would have used a more Reactive approach).</p><p>Then Combine arrived, and we replaced that third-party Promises library with the Combine’s counterparts. And finally, the time has come, allegedly to stay for very long, when that returned Publisher can be kicked out and replaced by the await keyword.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SxBkcVaUHU1vrhpKgpruGA.png" /><figcaption>The evolution of Swift Asynchronous Code in WELT iOS for the Location Manager</figcaption></figure><h3>The Combine Facade</h3><p>As expressed, the last version of our LocationManager before async/await is implemented with the help of Combine’s Publishers and Promises:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0d304bda07495a43b44ba0f18b3b27a5/href">https://medium.com/media/0d304bda07495a43b44ba0f18b3b27a5/href</a></iframe><p>As you can see, with the help of a promise instance property we are able to let this class client when the location is obtained, by retaining the returned publisher and reacting when updated:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a4d32be95b197d01a485931726098094/href">https://medium.com/media/a4d32be95b197d01a485931726098094/href</a></iframe><h3>From Combine to async/await with Continuations</h3><p>That approach fulfilled the goals we had in mind when creating a facade: it hides Apple’s CoreLocation implementation details and provides an easier API to deal with.</p><p>But in our insatiable desire for improvement, we realised that that API can still be simpler and more readable by converting it to async/await. How can we bridge the CoreLocation asynchronous delegate pattern to it? With the help of our new friend, the Checked Continuation.</p><p>In a similar fashion to the way we return a publisher that will be updated afterward via the promise property, we will now use a checked continuation to keep the program state when the updateLocation is called, to continue once the location is retrieved:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/78439e547ed2fc57399e782a07fd849e/href">https://medium.com/media/78439e547ed2fc57399e782a07fd849e/href</a></iframe><p>Here we:</p><ul><li>Create a typealias for our continuation type to make it more readable along with our class</li><li>Keep the location continuation in a property of that type</li><li>When the location is requested we start a continuation asking the CLLocationManager to update the location. That continuation reference is kept with our property so it can be resumed with the right value when that is obtained. (Or with an error)</li><li>In that manner, when we get the Core Location delegate callback with the updated location we resume our continuation with that value. That resumes the execution of the original function. If instead, we get an error, we resume it throwing it.</li></ul><p>That way, the code to call our manager is much simpler:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ac4433217413752ce0fb214cb63ff5f8/href">https://medium.com/media/ac4433217413752ce0fb214cb63ff5f8/href</a></iframe><p>Note how easy and clean is the call to obtain the location now, thanks to the new async/await syntax.</p><p>It is important to note that the continuation should be called to resume just once.</p><p>If we do not resume it the function client will be waiting forever holding the resources indefinitely</p><p>If we do it more than once “ala Reactive flow” your app will crash. No alternatives here.</p><p>Therefore, we have to be especially careful to dodge these calamities. In our case we avoid it by:</p><ul><li>Resuming the Continuation when CoreLocation returned an error. That way we are sure that it will be resumed at least once.</li><li>Setting the continuation to nil right after it is resumed. That way we are sure that it won’t be called more than once. If the location is required again it will be recreated.</li></ul><h3>Checked or Unsafe?</h3><p>Apple provides two types of continuations to be used: checked, and unsafe. As their name indicates, from the <a href="https://developer.apple.com/documentation/swift/checkedcontinuation">documentation</a>:</p><blockquote>CheckedContinuation performs runtime checks for missing or multiple resume operations. UnsafeContinuation avoids enforcing these invariants at runtime because it aims to be a low-overhead mechanism for interfacing Swift tasks with event loops, delegate methods, callbacks, and other non-async scheduling mechanisms. However, during development, the ability to verify that the invariants are being upheld in testing is important. Because both types have the same interface, you can replace one with the other in most circumstances, without making other changes.</blockquote><p>Therefore, if you want to use unsafe Continuations you have to:</p><ul><li>Be sure that your Continuation will always resume</li><li>Profile your app to verify that the extra checks that come along with Checked Continuations caused some performance degradation</li></ul><p>If any of these points are not true for you I suggest staying in the safe territory using Checked Continuations, given the cost of having missing or multiple resume operations.</p><h3><strong>Recapping</strong></h3><p>In this article, we acknowledged the role of Continuations within the new Swift Concurrency Model, and why it can be relevant for us.</p><p>After briefly reviewing how Facades are crucial to achieving clean code and the history of concurrency in our application, we went forward to migrate our Core Location Facade from Combine Promises to an async syntax API with the help of Continuations.</p><p>Next, we stated the consequences of not resuming our Continuation or making it more than once, and when to opt for Unsafe Continuations instead of Checked ones.</p><p>I hope you now have Continuations as another powerful tool in your toolbox, ready to be used when migrating from Callbacks or Delegate patterns to async/await. If you have questions, remarks or suggestions let me know.</p><p>Happy coding!!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d4a7bda4611b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/better-programming/convert-your-swift-facades-to-the-new-async-await-syntax-using-continuations-d4a7bda4611b">Convert Swift Facades Into async/await Syntax With Continuations</a> was originally published in <a href="https://betterprogramming.pub">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Swift Property Wrappers, User Defaults and Unique Default Values]]></title>
            <link>https://medium.com/axel-springer-tech/swift-property-wrappers-user-defaults-and-unique-default-values-e8725d7154a2?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/e8725d7154a2</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[app-development]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Mon, 21 Jun 2021 09:00:52 GMT</pubDate>
            <atom:updated>2021-08-02T12:21:51.031Z</atom:updated>
            <content:encoded><![CDATA[<h4>How to leverage the power of Property Wrappers to save and retrieve App Settings with a unique Default Value</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*hEfX_tN_8Fe2KbM5" /><figcaption>Photo by <a href="https://unsplash.com/@mrdongok?utm_source=medium&amp;utm_medium=referral">Rudy Dong</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>With the release of property wrappers together with Swift 5 and Xcode 11, many patterns can now be reimplemented in an <strong>easier, cleaner and faster approach.</strong> For instance, we use them at WELT to add an extra layer of logic to some UIColor instances, so the appropriate color value is provided depending on the user setting selected color mode. In the same way, we implemented a property wrapper that access <a href="https://firebase.google.com/products/remote-config">Firebase Remote Config</a> that provides the value specified by a key parameter. In this fashion we do not need all the repetitive code necessary to replicate this functionality without property wrappers.</p><p>Likewise, we wanted to implement a property wrapper that, given a key parameter, saves and retrieves a value from the UserDefaults. Furthermore, we needed to define<strong> a unique default value</strong> in case there is none stored, and we want to make it <strong>extensible to </strong><strong>RawRepresentable values so it can be used with enums</strong>. In this post we are going to see what the heck are property wrappers, in what cases they can be useful, and how we can extend them to implement our requirements.</p><h3>What are Property Wrappers?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*t5s3In3jJKz7HO3N" /><figcaption>Photo by <a href="https://unsplash.com/@marekpiwnicki?utm_source=medium&amp;utm_medium=referral">Marek Piwnicki</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>According to the <a href="https://docs.swift.org/swift-book/LanguageGuide/Properties.html">docs</a>:</p><blockquote>A property wrapper adds a layer of separation between code that manages how a property is stored and the code that defines a property.</blockquote><p>That is, i<strong>t is an extra layer that defines how a property is stored or computed when reading it.</strong> <strong>The main purpose of this pattern is to remove all the boilerplate code</strong> that you would have to write for each property that needs that logic. Again from the docs:</p><blockquote>For example, if you have properties that provide thread-safety checks or store their underlying data in a database, you have to write that code on every property. When you use a property wrapper, you write the management code <strong>once</strong> when you define the wrapper, and then reuse that management code by applying it to multiple properties.</blockquote><p>To illustrate, let’s take a look at this example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1dd5e21a93858d0c4e4be2b23b56e9ac/href">https://medium.com/media/1dd5e21a93858d0c4e4be2b23b56e9ac/href</a></iframe><p>Here we have defined a property wrapper that always provides the absolute of the set value. This way, we use the standard abs() function <strong>only once</strong>, instead of using it for every access of the property, or every getter and setter of those properties that need this logic. Similarly, the functionality is now encapsulated in its own struct, <strong>making the code cleaner and more readable</strong>.</p><h3>Our case: App Settings in User Defaults</h3><p>A very common pattern on iOS development is a wrapper over UserDefaults, in order to avoid the Read/Write code duplication, hide these details, and ensure testability by dependency injection. This is a perfect case to be updated with a property wrapper:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/69ab8831b9c51ff991e06f1bae7c3468/href">https://medium.com/media/69ab8831b9c51ff991e06f1bae7c3468/href</a></iframe><p>In this example, we wanted to know if the app onboarding screen was shown, in order to avoid displaying it again the second time the user opened the app. Thusly, in the RootViewModel , we add the wrapper to the property, and when the view did appear, we check that value. Note how easy it is here to access the stored value.</p><p>This code works, but it is obviously flawed. We return an optional, making the client responsible of checking whether there is a value, and providing a default value instead <strong>on every access.</strong></p><p>Could we move this logic into our property wrapper?</p><h3>Default Values</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*a7RfB5Bv_GOSf2lg" /><figcaption>Photo by <a href="https://unsplash.com/@enginakyurt?utm_source=medium&amp;utm_medium=referral">engin akyurt</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>In the same way a property wrapper avoids repetitive boilerplate code,<strong> we want to encapsulate the default value logic into the wrapper itself,</strong> so it always returns a non optional and sets the client free of implementing that logic:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/32e5bc4fdb8855847609dd77f522a5ab/href">https://medium.com/media/32e5bc4fdb8855847609dd77f522a5ab/href</a></iframe><p>This is implemented in the property wrapper by adding a defaultValue property and returning it in case nothing can be retrieved from the UserDefaults. In such manner, the property wrapper returns a non optional and the client can just add the required default value in the initializer.</p><p>Now it looks much better, but, what if we want to have <strong>a unique default value for all the application</strong>? In the previous example each client, in this case the RootViewModel , is able to specify the default value they want. This is totally fine for our onboarding use case, but what if we do not want to give the property wrapper client the power to define the default value?</p><blockquote>What if we want to have <strong>a unique default value for all the application</strong>?</blockquote><p>For instance, imagine we have an UserDefaults setting that holds whether we want to use our backend dev environment. <strong>We need this setting to be consistent along the whole application,</strong> that is, always point to the same backend environment to avoid an unconsistent and confusing state. On top of that, the user should be able to change this value anytime, for instance, if the QA Team wants to test a task against any environment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/424/1*UObvvhRWQGljT2iOgqkAiQ.png" /></figure><p>Again, we do not want the class where the property wrapper is applied, for instance the Network Fetcher, to bear the power of defining that default value. <strong>We want this logic to be unique and contained in its own class</strong>. For that, we take note of how Apple implements a generic key definition process of the SwiftUI <a href="https://developer.apple.com/documentation/swiftui/environment">Environment</a> property wrapper with <a href="https://developer.apple.com/documentation/swiftui/environmentvalues">EnvironmentValues</a>. Check these links for more information.</p><p>Going back to our example, we want to define a global unique default value for our environment setting. Given that what defines that setting uniquely is a <strong>key</strong>, <strong>we create a protocol that will act as a key to retrieve the value</strong>. This key protocol will contain <strong>a static property to hold the default value</strong> to be returned in case the setting is not yet in the user defaults.</p><p>As our pattern can return a generic value, we need an <a href="https://docs.swift.org/swift-book/LanguageGuide/Generics.html">associatedtype</a> within this protocol:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/40a2685527d133f42e7ec171dcf86cb2/href">https://medium.com/media/40a2685527d133f42e7ec171dcf86cb2/href</a></iframe><p>Next, we have to write an intermediate class to encapsulate the logic of retrieving the UserDefaults value given an AppSettingKey:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0a0bcaff2544455190dba2802fb37608/href">https://medium.com/media/0a0bcaff2544455190dba2802fb37608/href</a></iframe><p>Note how it will return the key static default value if there is no value stored in the container.</p><p>Now that we have this proxy to the UserDefaults, we can rewrite our property wrapper to use it:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dc428f2342a8d2140525767acce05e0e/href">https://medium.com/media/dc428f2342a8d2140525767acce05e0e/href</a></iframe><p>In the wrappedValue property it uses AppSettingsValues to retrieve the stored value.</p><p>Finally, we have to create a <strong>key for our specific setting case</strong>. It implements the AppSettingKey protocol and an extension of AppSettingsValues to provide the key as a <a href="https://developer.apple.com/documentation/swift/referencewritablekeypath">ReferenceWritableKeyPath</a> :</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a395f8c24d815a1f82c800e79e59f143/href">https://medium.com/media/a395f8c24d815a1f82c800e79e59f143/href</a></iframe><p>Once we have everything, we can use it effortlessly:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1be39381617634c7f04bae915109db6e/href">https://medium.com/media/1be39381617634c7f04bae915109db6e/href</a></iframe><p>We just pass the AppSettingValueskeypath created together with the UseDevEnvironmentKey to the property wrapper initializer, and it’s ready to use. That simple!</p><h3>But I have an enum!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*K2DG61uzN6hkAK0k" /><figcaption>Photo by <a href="https://unsplash.com/@itssammoqadam?utm_source=medium&amp;utm_medium=referral">Sam Moqadam</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Again, the example is doing what we want, but we are not quite there yet. As you saw, we use a boolean value to determine which environment we are going to point: if it is true we use the development endpoints, otherwise production. This is suboptimal though.</p><p>What if, on top of dev and prod, we also have a test environment? How can improve our code to handle multiple cases? Cases?, yeah, <strong>we need an </strong><strong>enum</strong> But wait, it is not so simple, even if we can change our environment data representation from a boolean to an enum, this type cannot be stored by default in the UserDefaults. <strong>We need to make that enum conform to the </strong><a href="https://developer.apple.com/documentation/swift/rawrepresentable"><strong>RawRepresentable</strong></a><strong> protocol, by specifying a string, integer, or floating-point raw type.</strong> The Swift compiler automatically adds RawRepresentable conformance when doing it:</p><pre>public enum Environment: String {<br>  case development<br>  case test<br>  case production<br>}</pre><p><strong>Once we have a raw value for each case, we can store that value in UserDefaults</strong>, and when reading it, we will create an Environment instance from the raw value. This is implemented by creating its own App Setting Key protocol to enforce that the associatedtype conforms to RawRepresentable and adding a new subscript function in the AppSettingsValues class:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bb6666a44b471cced77f3ac1924f8b34/href">https://medium.com/media/bb6666a44b471cced77f3ac1924f8b34/href</a></iframe><p>Note how powerful is the where keyword in swift, it allows us to easily filter out values, in this case those that don’t conform to RawRepresentableAppSettingKey</p><h3>Epilogue: Testability</h3><p>Without delving too deep in a topic that deserves its own post, we ensure testability by allowing the injection of the needed dependencies. The UserDefaults container is passed in the initializer of the AppSettingsValues, so we can inject it when testing. For instance, we could create our own UserDefaults instance other than .default, by initializing it with a suite name. Once we have that instance, we pass it to create the AppSettingsValues, and set this one to the property of the AppSettings property wrapper:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/594e86487d7d149e37f867aeeb8f0138/href">https://medium.com/media/594e86487d7d149e37f867aeeb8f0138/href</a></iframe><h3>Wrapping Up</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ScGrwD5iTsdbv1SK" /><figcaption>Photo by <a href="https://unsplash.com/@matthewhenry?utm_source=medium&amp;utm_medium=referral">Matthew Henry</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>We went through many topics today:</p><ul><li>What are <strong>property wrappers </strong>and what are they used for</li><li>How can we apply property wrappers to<strong> read and write values from User Defaults</strong></li><li>How can we add a default value for each use case of our User Defaults</li><li>How can specify a unique global default value for a property wrapper key</li><li>How can we enhance our User Defaults property wrapper <strong>to apply it to enums</strong></li><li>How can we <strong>ensure testability</strong> by injecting our User Defaults container</li></ul><p>I hope you liked this story and can profit from it. If you have any question or suggestion do not hesitate to drop a message below. I would like to thank my colleagues <a href="https://medium.com/u/48279cca1251">Ivan Lisovyi</a> and <a href="https://medium.com/u/482610e21173">Haroon Ur Rasheed</a> for their critical contribution on this topic.<br>Happy wrapping!!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e8725d7154a2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/axel-springer-tech/swift-property-wrappers-user-defaults-and-unique-default-values-e8725d7154a2">Swift Property Wrappers, User Defaults and Unique Default Values</a> was originally published in <a href="https://medium.com/axel-springer-tech">Axel Springer Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SwiftUI in WELT: First Blood]]></title>
            <link>https://medium.com/axel-springer-tech/swiftui-in-welt-first-blood-f26e0bb5aec2?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/f26e0bb5aec2</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Thu, 06 May 2021 10:20:32 GMT</pubDate>
            <atom:updated>2021-05-17T10:33:34.768Z</atom:updated>
            <content:encoded><![CDATA[<h4>Or how we started using SwiftUI in Production Code without (major) Headaches</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w9Qx-_oReedtEJctJ9bDNg.jpeg" /></figure><p>With the Product Owner’s green light for dropping the <strong>support of iOS 12</strong> downwards, a new world of juicy possibilities emerged in our development horizon. Together with iOS 13 two major new Apple frameworks were released: Combine and <strong>SwiftUI</strong>, the new framework to design and develop user interfaces <strong>declaratively and with less code.</strong> For the former we lost no time in replacing our aged third party library and start using Combine everywhere Reactive Programming or Promises were applied. For the latter, SwiftUI, even if we could barely contain our excitement to see it running our user interface, we were more cautious given the early mixed feedback from the iOS devs community.</p><p>In this story I want to present the <strong>process we followed to start using SwiftUI in our production codebase</strong>, from the planning strategy to the actual code writing. We will see why it might be good idea in the first place, how we can do it in a safe and interesting manner and what troubles we encountered and how we solved them. At the end you will find the conclusion with our personal opinion based on experience and tips for your first rendezvous with SwiftUI.</p><p>So, same as John Rambo in the first instalment of the franchise, it was time to start walking towards our sure fate and plan how we can integrate SwiftUI in our production environment. Notwithstanding, before starting writing code, a moment of pause and reflection is necessary: why do we even need to do that? Is it just the developer’s frenzy of new technologies, or will we really profit from it?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jgTTlT05pc-iJ_oL" /><figcaption>Photo by <a href="https://unsplash.com/@bradencollum?utm_source=medium&amp;utm_medium=referral">Braden Collum</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Why?</h3><p>Don’t panic, <strong>this is not going to be the zillionth post comparing SwiftUI and UIKit</strong>. But still, it is important to mention what was the drive when we decided to trigger the process.</p><p>For starters, as I said before, SwiftUI helps to create the same UI design as UIKit with <strong>significantly less code</strong>. The advantages that this produces are obvious: generally less code means better <strong>Readability</strong>, easier <strong>Maintainability</strong>, more <strong>Efficiency</strong> and substantially fewer expected <strong>Workload</strong>, that is, we will spend less working hours to achieve the same results, not only because of the amount of code required, but also because of the <a href="https://developer.apple.com/news/?id=8vkqn3ih">Live Preview</a> used when development. So, with SwiftUI we expect to …</p><ul><li>Improve <strong>Readability</strong></li><li>Make the code <strong>easier to maintain</strong></li><li>Enhance the code’s <strong>efficiency</strong></li><li>Reduce the expected <strong>Workload</strong></li></ul><p>Not bad uh? I am convinced that this is just enough to sustain our decision to start using SwiftUI. But on top of that, with this new framework we will move even further in the direction of a more reactive and declarative syntax, a way that as remarked we started years ago and followed when introducing Combine. Because yeah, do you know what uses SwiftUI to implement its reactive logic? Bingo, <strong>Combine</strong>!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*g2Z_QXksfhG8VvmNXcA2Xg.gif" /><figcaption>Bingo!</figcaption></figure><p>Apart from that, SwiftUI is allegedly easy to use, the code is clean and it can be integrated perfectly with UIKit. That means that we can conveniently migrate some parts of our UI code to SwiftUI, while the rest remains written within the bounds of the UIKit syntax.</p><p>Last but not least, we listen to our yearning to try something that might change we way we think and develop User Interfaces for many years to come. And we wanted to do that in <strong>real fire production code</strong>, the best arena to learn with the mistakes encountered along the way, both ours and those caused by such an early stage tool as SwiftUI.</p><p>Alrighty! We have now a why, what is missing to start working with it? Of course, a how!</p><h3>How?</h3><p>What a good question, how can we start writing our UI in SwiftUI? There are not many alternatives at this point, either we wait for new UI features to pop out from our backlog, or <strong>we migrate some of the already existing screens</strong>. The second option is less risky and more convenient to mitigate the learning curve pain of adapting this new technology. Basically, we just want to rewrite a simple yet custom screen. We want to find some <strong>challenges along the way, the key to learning something new.</strong></p><blockquote>Either we wait for new UI features to pop out from our backlog, or we migrate some of the already existing screens</blockquote><p>The biggest caveat of this approach is the apparent lack of added value, or at least short term added value, outside of the devs team. After all, we are just replacing one screen … with the exact same screen. Thankfully, we have a negotiated time budget for technical improvements.</p><p>Given the clear benefits of refactoring the existing UIKit based Views to use SwiftUI (<strong>contained risks, <em>smooth</em> learning</strong>) and being able to endure the few drawbacks that might bring, we opted for that option. Thus, we then had to find an existing screen that matches our criteria, simple, but yet with some custom complexity.</p><p>The Stocks view is perfect for that. A table with custom designed cells that represents displaying a data model retrieved from a backend endpoint, together with a pull-to-refresh control that triggers the refresh of the screen content:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/420/1*DDCgW6o5QPrwvmuT4cn_og.jpeg" /><figcaption>The Stocks screen, our Guinea Pig</figcaption></figure><p>Thanks to UIHostingController, it is <strong>painless</strong> to integrate this SwiftUI view back into the UIKit Navigation Controllers architecture.</p><h3>Challenges</h3><p>The development process of the basic features of this screen is very straightforward: the former UIKit UITableView is now replaced with a SwiftUI List, the cells are easily buildable with an HStack that composes the Texts. Those in turn, are rendered with different background colours that are applicable as <a href="https://www.hackingwithswift.com/books/ios-swiftui/custom-modifiers">view modifiers</a>. It is here where SwiftUI supposedly excels and I can certify; what it used to be many lines of UIKit based code, <strong>it is now just a bunch of much more readable declarative code lines</strong>. In particular, the concept of having a single entry point for describing a view, is just awesome and much simpler to read and build. Plus one, SwiftUI!</p><blockquote>What it used to be many lines of UIKit code, <strong>it now just a bunch of much more readable declarative code lines</strong>.</blockquote><p>Granted that, It is when we bring our rebel side and try to go off road that we start suffering, <strong>especially if, still supporting iOS 13, are obliged to work with the first version of the framework.</strong></p><p>For instance, at this time <strong>SwiftUI does not include a refresh control</strong> that mimics the action of the former and beloved UIKit’sUIRefreshControl, so we ourselves have to build it. Or better said, we can rely on this <a href="https://github.com/siteline/SwiftUIRefresh">external library</a> that achieves it by introspecting the hierarchy of the relevant UITableView that stands behind the SwiftUI scenes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/605/1*_K0lIBlDTJA4ESs71wrrpA.jpeg" /><figcaption>We might have to do some shady job to custom our design with SwiftUI</figcaption></figure><p><strong><em>Introspect </em>is a word that you will hear very often while working with SwiftUI</strong>: the first resort to be used in order to implement something not supported out of the box by SwiftUI <strong>will be to introspect the underlying elements behind the SwiftUI components</strong>, most likely UIKit ones, to modify them according to our requirements.<a href="https://github.com/siteline/SwiftUI-Introspect"> SwiftUI-Introspect</a> might be the first tool in your toolset when the time comes. The downside of this approach is obvious, apart from having to rely on an external dependency, with any new version of SwiftUI new changes in the implementation <strong>might come and break your flow</strong>. But still, until the iOS SDK includes all these components, there is not much we can do.</p><p>Likewise, ase we wanted to remove the extra separators that appear below the list by default, we had to modify the tableFooterView property of the table view appearance on appear, and reset it on disappear:</p><pre>.onAppear {</pre><pre>UITableView.appearance().tableFooterView = UIView()</pre><pre>}</pre><pre>.onDisappear {</pre><pre>UITableView.appearance().tableFooterView = nil</pre><pre>}</pre><p>Another tweak to the UIKit underlying element to achieve our visual demands. Note that this happens only on iOS13, on iOS 14 by default there are no separators under the list.</p><p>Furthermore, the biggest challenge we face when working with SwiftUI is coming up with an architecture that binds our data to the view in a <strong>reactive way</strong>.</p><p>The true difficulty here resides not so much in implementing those bindings, but in shifting the mindset paradigm away from the UIKit-friendly architectures, such as MVC, VIPER or even MVVM. <strong>Now SwiftUI forces us to change our attitude into a new way of thinking</strong>, where of course the main premises of Clean Code stay, but declarativeness and reactiveness prevail. And while SwiftUI together with Combine provide the right tools for building a small sized codebase, <strong>for a larger, more complex, feature scalable and modular App it falls short.</strong></p><blockquote>For a larger, more complex, feature scalable and modular App SwiftUI falls short.</blockquote><p>To illustrate without delving too deep, it is difficult to find a solution to persist our (complex) App State that is scalable, and at the same time easy to mutate along the different views. The given <a href="https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-state-property-wrapper">State</a> property wrapper used by SwiftUI should be used with simple struct types (Int, String, Array …) and <strong>not be shared with other views</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yrSm1yl9y24Lnvkc5sLYIg.jpeg" /><figcaption>The more modular, the cooler</figcaption></figure><p>In like fashion, it is not possible to split a large app state into smaller ones, for instance, to be used in different modules. With a more modular approach, each package would only have access to the state elements relevant to its functionality, making the architecture much more encapsulated and safe. As a consequence of these points, and also because of the lack of tools and documentation on the subject, <strong>it is very difficult to test a SwiftUI view or its side effects</strong>. This is very important; testability is a <a href="https://www.merriam-webster.com/dictionary/sine%20qua%20non"><em>sine qua non</em></a> condition for our business logic implementation.</p><p>Consequently, and thinking long term, we use <a href="https://github.com/pointfreeco/swift-composable-architecture">The Composable Architecture</a> to address these issues. TCA is a open source library that provides:</p><blockquote>A few core tools that can be used to build applications of varying purpose and complexity. It provides compelling stories that you can follow to solve many problems you encounter day-to-day when building applications, such as, <strong>State management, Composition, Side effects and Testing</strong></blockquote><p>While TCA is optimal for SwiftUI, it can be also used together withUIKit, as well as on every other Apple platform (iOS, macOS, tvOS, and watchOS). If you want to know more about it plus more Swift functional programming topics, visit their Video/Blog site <a href="http://pointfree.co">pointfree.co</a>.</p><p>In that manner we solve the problems we enumerated before: we can now create our Stocks View in a separate, encapsulated and fully testable module, that fits perfectly into our modular App.</p><p>In short, when working with SwiftUI we faced these obstacles:</p><ul><li>Lack of tools to display <em>complex</em> design elements (<strong>Refresh Control</strong>, List separators …)</li><li>No <strong>scalable and composable</strong> App State</li><li><strong>Cumbersome Testability</strong></li></ul><p>For now we used Introspect and TCA to solve these issues, but we are confident that SwiftUI itself improves with future versions as it did with SwiftUI 2 on iOS 14.</p><h3>The Aftermath</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WbqQA9AJ15gGkZX1" /><figcaption>Photo by <a href="https://unsplash.com/@jplenio?utm_source=medium&amp;utm_medium=referral">Johannes Plenio</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>In this story I just described how we introduced SwiftUI in our <strong>production code</strong>. We did it to learn and to <strong>have a more declarative, readable, efficient, smaller and easier to maintain code</strong>. Besides, I explained how migrating a <strong>simple screen would be the easiest entry point to start dealing with it</strong>. And furthermore, we know now what are <strong>the main challenges</strong> when venturing into this up-to-now uncharted territory, and what weapons do we have to emerge victorious.</p><p>I would like to thank my colleague <a href="https://medium.com/u/48279cca1251">Ivan Lisovyi</a> for the huge contribution to this topic. As always, if you have any suggestion, correction or comment drop a message below.</p><p>Happy <strong>SwiftUIting</strong>!!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f26e0bb5aec2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/axel-springer-tech/swiftui-in-welt-first-blood-f26e0bb5aec2">SwiftUI in WELT: First Blood</a> was originally published in <a href="https://medium.com/axel-springer-tech">Axel Springer Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bring your old iOS Library back to Life in just few easy Steps]]></title>
            <link>https://medium.com/axel-springer-tech/bring-your-old-ios-library-back-to-life-in-just-few-easy-steps-e4163126fd38?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/e4163126fd38</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Thu, 11 Feb 2021 09:59:25 GMT</pubDate>
            <atom:updated>2021-02-15T22:53:53.821Z</atom:updated>
            <content:encoded><![CDATA[<h4>Revive an outdated Package with a new and fresh Look</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*E232pq_Kny5VsurX" /><figcaption>Photo by <a href="https://unsplash.com/@sonjalangford?utm_source=medium&amp;utm_medium=referral">Sonja Langford</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Yeah, it happens. Time flies. <em>“Tempus Fugit” </em>as the cool people used to say. It could be a new grey hair or wrinkle when facing the merciless mirror, the sudden realisation that your team did not win the league in few years or <strong>an iOS library written for iOS 8</strong>. And the sooner we accept that fact, the sooner we can cope with it and go on with our lives. <a href="https://en.wikipedia.org/wiki/Serenity_Prayer"><em>Accept the things I cannot change</em></a><em>, don’t look back </em>and all this. Only that there is something we can change here. We can retake our decrepit library, give it some energizing love and resurrect it with a fresh and youthful look.</p><p>On <a href="https://github.com/spring-media">NMT</a> we use any given chance to encapsulate an implemented feature into a library, and if time and privacy allow it, publish it Open Source for the common good. The proof is in the pudding: back in 2016 we extracted the Homescreen Navigation of our <a href="https://apps.apple.com/us/app/welt-news-nachrichten-live/id340021100">WELT News App</a> into <a href="https://github.com/spring-media/LazyPages"><strong>LazyPages</strong></a><strong>, a highly customizable library that helps you to show a scrollable list of view controllers synchronized with an index menu</strong>. With Lazy Pages <strong>you can lazy load your view controllers</strong>, instead of having them all in memory when creating it.</p><p>But, as time is impermanent, so is the UX &amp; UI Design of a product whose owner is eager to improve. For a time we opted for a kinda like <a href="https://ux.stackexchange.com/questions/86941/is-it-ok-to-use-hamburger-menus-in-ios">Burger Menu</a> to navigate among the sections of our app, to later realise that the original Lazy Pages approach produced more traffic and optimized our app’s user experience. It was time then to open the storehouse of memory searching for Lazy Pages again.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*eAlIkBVzYHt2-Lxz1j_FzA.gif" /><figcaption>Lazy Pages doing lazy things</figcaption></figure><p>The advantages of both modularising your architecture and publishing Open Source are common knowledge nowadays, so I won’t delve into these topics here. Instead, I’d like to focus on the <strong>why and how</strong> we can bring these old libraries back to life.</p><h3>Why?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*lZQ3kKsCsEz07mYX4TRfDA.png" /></figure><p>Of course, as with any other aspect in our lives, the big question comes: <strong>why?</strong> Why spending even a tiny bit of our precious time in that? Well, for us the answer was easy; we needed that functionality again, and we needed it in production. That means that, as any other piece of our code, it had to be adapted to the latest requirements.</p><p>But even if we are not going to use it, <strong>maintaining our Open Source libraries is very convenient</strong>. Firstly, because that way it could still be used by the community. Likewise,<strong> keeping a product up to date would encourage other users to contribute</strong>, and in that manner, leverage the necessary effort to sustain a well looking product.</p><p>In addition, our personal or brand name will still be linked to a well maintained product, <strong>avoiding the bad impression produced by the unfortunate “last commit three years ago”</strong>.</p><h3>I still don’t wanna do it!</h3><p>Ok ok, there are cases when we do not want to spend time on it. Maybe our project is redundant because Apple already provided that functionality in a later version of the SDK, as they did with <a href="https://developer.apple.com/documentation/combine">Combine</a> for Reactive Programming. Or perhaps the <strong>huge amount of required effort to migrate</strong> from ObjC to the latest Swift version or to make it compile with the newest SDK makes it simply not worth it.</p><p>In that case there is still something we can do instead of deleting it. We can <a href="https://github.blog/2017-11-08-archiving-repositories"><strong>archive</strong></a> it. That means that we are not actively working on that project, and likewise we won’t accept any further contribution. It makes it <strong>read-only</strong>:</p><blockquote>Just because a repository isn’t actively developed anymore and you don’t want to accept additional contributions doesn’t mean you want to delete it. Now archive repositories on GitHub to make them read-only.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2r_oHY6dKyfu8iTT" /><figcaption>Photo by <a href="https://unsplash.com/@nananadolgo?utm_source=medium&amp;utm_medium=referral">Nana Smirnova</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Just like that we can quickly show our userbase that the library is no longer being updated so they should use it at their own risk, and by the same token it will probably need a bit of refurbishing before using it.</p><p>But be wary of this option; as stated above, <strong>archiving means that no further contribution is allowed in your repo</strong>. It could be the case that you don’t have time to enhance your owned library, but any other kind fellow developer might be eager to do that. If we archive it they won’t be able to do it anymore.</p><h3>The Quest for Eternal Youth</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/850/1*2w2M69O71fN3AsoQpQQQ8A.jpeg" /></figure><p>Yeah, you convinced me, I want to renovate or maintain that old library of mine. What should I do? Can you provide me a checklist to achieve it? In order to update our library, we should:</p><ul><li>Migrate it to the <strong>last Swift Version</strong></li><li>Make it <strong>compile with the last iOS SDK</strong></li><li>Use <strong>new technologies</strong></li><li>Convert it to a <strong>Swift Package</strong> and support <strong>Swift Package Manager</strong></li><li>Update your <strong>README</strong> file and <strong>draft a Release</strong></li><li>Add it to the <strong>Swift Package Index</strong></li></ul><p>Here we go! Firstly and foremost, we have to …</p><h4>Migrate it to the last Swift Version</h4><p>Yup, if we are going to make it, we have to <a href="https://www.amazon.com/Eat-That-Frog-Great-Procrastinating/dp/162656941X">eat that frog first</a>. So in the case that we have an old Swift version or, <strong>even worse, if our library is still in Objective C</strong>, we have to migrate to the last Swift version so it can benefit of all the advantages of the language. We are many developers that would prioritise a Swift codebase over Objective C almost blindly, among other reasons because of the easiness of the package integration and future usage. That brings us to the next topic , it …</p><h4>Should compile with the last iOS SDK</h4><p>Yeah, if we migrated to the last Swift version this step was probably required, but notwithstanding it is worth remarking it. Your library should be buildable with the last OS SDK version so it can be usable in any project. Needless to say, this does not mean that we should supporting older iOS versions, we can still set our minimum deployment target to a previous value. We will delve into this when talking of SPM, but now that we are using the latest iOS version, we can …</p><h4>Use the newest technologies</h4><p>Together with newer versions of the iOS SDK, <strong>new features and technologies APIs are shipped by Apple</strong>, APIs that can be integrated in your library replacing or enhancing your old codebase. For instance, if you used reactive programming with <a href="https://github.com/ReactiveX/RxSwift">RxSwift</a> you can now use <a href="https://developer.apple.com/documentation/combine">Combine</a>, getting rid of one big dependency <strong>and thus decreasing the build time</strong>. If you were using ARKit, you can now use the brand-new Depth API introduced in ARKit 4, thus making your package much more attractive for the community.</p><p>Once we have our codebase ready, it is time to …</p><h4>Convert it to a Swift Package and support Swift Package Manager (SPM)</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/840/1*hjXv9LZxbZSM1Wn_xSMktQ.png" /></figure><p>Whether your library is older than Xcode 8 or you preferred not to support it due to its early stage,<strong> now it is essential that your package is installable through </strong><a href="https://swift.org/package-manager/"><strong>Swift Package Manager</strong></a>. With <a href="https://github.com/spring-media/LazyPages#installation">Lazy Pages</a> we were <strong>as far as to remove the support for CocoaPods</strong>, in order to simplify the installation process.</p><p>SPM is the standard tool build by Apple to distribute Swift packages. It is fully integrated in Xcode and automatically manages all the dependency’s dependencies, what makes the process painless and transparent. <a href="https://developer.apple.com/documentation/xcode/creating_a_standalone_swift_package_with_xcode">Here</a> you can delve deeper into how to create a standalone Swift Package, or convert your existing codebase.</p><p>If you already have your shiny new Swift Package, you should …</p><h4>Update the README file and draft a new Release</h4><p>After the changes above it is <strong>very likely that the information in the README.md file should be updated</strong>. Your requirements are different now: you require higher versions of Xcode, iOS and Swift, and furthermore, it should be stated how to install it via SPM.</p><p>Moreover, if the changes forced your to modify your library’s public interface it is time <strong>to edit your usage code snippets</strong>, to include the new additions.</p><p>Similarly, a <strong>new library version should be drafted</strong>, with a proper tag version, title, and a short description mentioning whether this new release <strong>included breaking changes</strong>, so your users can decide to install it or postpone the effort of adapting to the new modifications.</p><p>All your hard work deserves to be acknowledged. You can finally …</p><h4>Add it to the Swift Package Index</h4><p>These days, with the immense amount of information and resources available in the internet, it is likely that your library gets lost it is not somehow indexed. To avoid that, you can of course write a blog post about it, send it to your favourite iOS developer community newsletter, or add it to the <a href="https://swiftpackageindex.com/">Swift Package Index</a>.</p><p><strong>Swift Package Index is the place to find Swift packages</strong>, indexing at the moment 3,486 packages and 53,590 versions, and growing everyday. To add your package there, check their <a href="https://github.com/SwiftPackageIndex/PackageList">Master List repository</a> to submit it. As they say:</p><blockquote>Please feel free to submit your own, or other people’s repositories to this list. There are a few requirements, but they aren’t onerous.</blockquote><h3>That’s it!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*C82EcxNMyC_hER9_38FIiw.jpeg" /></figure><p>That was it, not so tough right? Now your team and the community are thankful for your shiny package, that can be used again as if it were totally new.</p><p>In this post we have seen <strong>why and when</strong> it is important to maintain and keep our libraries up to date,<strong> how to do it</strong>, and when it is not worth doing it. Even in the latter case we can do something with it.</p><p>Certainly i might have missed some important steps along the process, if you think so or have any other suggestion please add a comment here.</p><p>Carpe Diem!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e4163126fd38" width="1" height="1" alt=""><hr><p><a href="https://medium.com/axel-springer-tech/bring-your-old-ios-library-back-to-life-in-just-few-easy-steps-e4163126fd38">Bring your old iOS Library back to Life in just few easy Steps</a> was originally published in <a href="https://medium.com/axel-springer-tech">Axel Springer Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Wink! Or How your Users can interact with your iOS App by changing their Face Expressions]]></title>
            <link>https://medium.com/axel-springer-tech/wink-or-how-your-users-can-interact-with-your-ios-app-by-changing-their-face-expressions-cb7634096a82?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/cb7634096a82</guid>
            <category><![CDATA[ar]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Sun, 13 Dec 2020 18:40:17 GMT</pubDate>
            <atom:updated>2020-12-13T18:40:17.437Z</atom:updated>
            <content:encoded><![CDATA[<h4>Get notified reactively when the user changes the face expression with <a href="https://github.com/toupper/Wink">Wink</a></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LNKbNcmxyhBZhet7hrnT8g.png" /></figure><p>In my previous stories <a href="https://medium.com/better-programming/warhol-face-detection-made-easy-on-ios-4b146b87b7d0"><strong>Warhol</strong></a> and <a href="https://medium.com/swlh/warhol-ii-compose-your-overlay-on-top-of-the-detected-face-hassle-free-for-ios-ae5b8d40924d"><strong>Warhol II</strong></a> I talked about how we can easily detect the user face features and render our desired overlay on top of them thanks to <a href="https://github.com/toupper/Warhol">Warhol</a>, a library of my own. For that I used the Apple <a href="https://developer.apple.com/documentation/vision">Vision</a> Framework, that among other things supports the detection of items such and face and face landmarks. Furthermore the Warhol client shall not deal with Vision at all, as it is hidden behind the library interface thus alleviating the effort of the client implementation.</p><p>During Warhol’s development process something came to my mind. Wouldn’t it be cool if, on top of the user features, we could detect face expressions as well? So, not only detect where is the user’s eye, but also when they wink it, open the mouth or smile. The use cases for this functionality are numerous; <strong>no more swipe left or right on Tinder but wink left or right</strong>, help disabled users to interact with our app via face gestures or make your videogame character jump by opening the mouth.</p><p>Unfortunately Vision does not offer such feature, but do not fear, <strong>thanks to ARKit we can obtain information about the pose, topology, and expression of a face that ARKit detects in the front camera feed</strong>. These capabilities were introduced on iOS 11 and requires a device with TrueDepth camera. This camera replaces the front one on the iPhone X and later, being capable of capturing 3D information for Face ID authentication and Animoji.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NIrydjvHT8R9Kuez6proHw.png" /></figure><p>With that goal I developed <a href="https://github.com/toupper/Wink"><strong>Wink</strong></a>. <strong>Wink is a light reactive library written in Swift that makes easy the process of Face Expressions Detection (blink, smile, mouth open…) on IOS</strong>. It detects a default set of user face expressions using the TrueDepth camera of the iPhone,<strong> and notifies you on real time using </strong><a href="https://developer.apple.com/documentation/combine"><strong>Combine</strong></a><strong>, Apple’s reactive framework.</strong> That way, the Wink client does not need to know anything about ARKit, only if they want to extend the set of Face Expressions detected.</p><blockquote><strong>Wink is a light reactive library written in Swift that makes easy the process of Face Expressions Detection (blink, smile, mouth open…) on IOS</strong></blockquote><p><strong>Wink provides a view controller with the camera view, and a Combine </strong><strong>AnyPublisher that gets updated whenever the user changes the expressions. </strong>We can then add that UIViewController to our view hierarchy and react to any any new user face gesture. In case we do not want to show the camera view, we can just hide it or resize it and place according to our requirements.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/926/1*8zkZG5Jf3VJHexR4yqxXYA.png" /><figcaption>wink!</figcaption></figure><h3>Behind the Scenes</h3><p>In this section we are going to see how Wink uses <a href="https://developer.apple.com/augmented-reality/">ARKit</a> to to detect the user face expressions. If you wanna start using Wink right away in your app, go directly to the next passage.</p><p>As in any other AR experience with SceneKit, we need to create an ARSCNView instance, that will be added to our FacialExpressionDetectorViewController view.</p><p>After that we set the delegate to our class, that will receive the view’s AR scene information with SceneKit content. Once we have added the view to our hierarchy and set the delegate, we call to run the session with a face tracking configuration in viewWillAppear:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/65262d57fb5f3d94577745f0470c3dd4/href">https://medium.com/media/65262d57fb5f3d94577745f0470c3dd4/href</a></iframe><p>In the same way, we should not forget to pause it when the view will disappear.</p><p>Once we have setup the ARSCNView that will display the <strong>AR</strong> experience and run the session, it is time to start detecting the face expressions and pass them to the client. We do this through the ARSCNViewDelegate methods:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8ba5ff6012ceb2c3c784fb04733da980/href">https://medium.com/media/8ba5ff6012ceb2c3c784fb04733da980/href</a></iframe><p>Firstly, we have to return a new node with the representation of face topology in the our scene view for each 3D anchor, that is, the position and orientation of something of interest in the user’s face. If these concepts are too advanced for you or you need to refresh them, this <a href="https://www.raywenderlich.com/378-augmented-reality-and-arkit-tutorial">tutorial</a> is perfect to get familiar with the ARKit basics.</p><p>Now that we have a node for each anchor, ARKit will let us know whenever the node was updated, that is, <strong>when new information was obtained from the scene view</strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6b122e4b799111dbc6f773d647d6d2a3/href">https://medium.com/media/6b122e4b799111dbc6f773d647d6d2a3/href</a></iframe><p>Here we refresh our nodes with the face anchors, and proceed to detect the facial expressions from the ARFaceAnchor:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5efa7ef259981bff76283dbf725f0873/href">https://medium.com/media/5efa7ef259981bff76283dbf725f0873/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/414/1*GXZETrC7Bz2yE3A6VtjQgg.jpeg" /><figcaption>Not a new Avenger, but a face with AR Nodes. See how ARKit is able to detect them in 3D thanks to the True Depth Camera</figcaption></figure><p>To better understand this, we need to know what is aFacialExpressionAnalyzer in Wink. A FacialExpressionAnalyzer is a struct encapsulating the data needed to detect one specific face expression:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/003a4f25a017a0c42701e400d1e4f3ca/href">https://medium.com/media/003a4f25a017a0c42701e400d1e4f3ca/href</a></iframe><p>It contains the Wink FacialExpression object that represents the gestures in the user’s face (mouthSmileLeft, mouthSmileRight …), the AR object that it corresponds to, <strong>and the minimum valid coefficient to accept a facial expression as actually happening</strong>. As pointed before, Wink comes with a default set of analyzers:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fd9bfb3b1b09e061ea51b4c3cc860672/href">https://medium.com/media/fd9bfb3b1b09e061ea51b4c3cc860672/href</a></iframe><p>that is created and assigned inFacialExpressionDetectorViewController:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1a4095dea95b0b8ba29cd017f8d26145/href">https://medium.com/media/1a4095dea95b0b8ba29cd017f8d26145/href</a></iframe><p>As we will see later, it is very easy to extend this functionality with our own with having to modify the code, thus following the <a href="https://stackify.com/solid-design-open-closed-principle/"><strong>Open-Closed Principle</strong></a>:</p><blockquote>“Software entities should be open for extension, but closed for modification”.</blockquote><p>Going back to detectFacialExpression(from anchor: ARFaceAnchor), we see how we compactMap the analyzers into face expressions whose current value is higher than the minimumValidCoefficient, meaning that the user is actually doing that gesture as much as our requirements accepts them. Once we have the array with the current Face Expressions, we send it through the Combine&#39;sPassthroughSubject object.</p><h3>Let’s Play!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DJQh9Dvc6w05oLun" /><figcaption>Photo by <a href="https://unsplash.com/@jrlawrence?utm_source=medium&amp;utm_medium=referral">Jeremiah Lawrence</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>This was all very interesting, but to the developer who wants to roll fast it will be probably not so useful. <strong>After all, the purpose of Wink is to ease the process of face expression detections without the need of dealing with the compelling but arcane world of ARKit.</strong></p><p>To start using Wink in your screen’sUIViewController, create a new instance of FacialExpressionDetectorViewController and add it to the former through the usual process of <a href="https://www.hackingwithswift.com/example-code/uikit/how-to-use-view-controller-containment">view controller containment</a>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cb607c37cecec0fc673716d6754bfaf5/href">https://medium.com/media/cb607c37cecec0fc673716d6754bfaf5/href</a></iframe><p>You might then want to place it as you wish adjusting the constraints, or hide it if you don’t want the camera view to be shown. In this case we add it to the upper left corner of our view:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7df8f3cf171349c31568e8da5b405057/href">https://medium.com/media/7df8f3cf171349c31568e8da5b405057/href</a></iframe><p>After these steps, it comes the climax of the movie; <strong>we have to subscribe to the User Face Expression changes, sinking the Combine publisher that come with the </strong><strong>FacialExpressionDetectorViewController:</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/89dd8c35083fea712f1c93172c242e7d/href">https://medium.com/media/89dd8c35083fea712f1c93172c242e7d/href</a></iframe><p>In our sample app we are just describing the current face expressions with the help of a FacialExpression extension, in your case here is where you react to the user face expression changes to trigger the desired action:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F490460878%3Fapp_id%3D122963&amp;dntp=1&amp;display_name=Vimeo&amp;url=https%3A%2F%2Fvimeo.com%2F490460878&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F1014557126_295x166.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=vimeo" width="632" height="1366" frameborder="0" scrolling="no"><a href="https://medium.com/media/292a67306fa8d55e4b333d0a1fe27676/href">https://medium.com/media/292a67306fa8d55e4b333d0a1fe27676/href</a></iframe><p>In this debug sample you can see how Wink detects my face expressions, and how the client react to them displaying a description of the retrieved gestures. <strong>The statistics and the web are part of the Wink debug mode</strong>, they can be of course be disabled in production.</p><p>That’s it! The process of using Wink is very straightforward, just four steps:</p><ul><li>Create an instance of <strong>FacialExpressionDetectorViewController</strong></li><li>Add it your view controller</li><li><strong>Place</strong> or <strong>hide</strong> the camera view according to your requirements</li><li><strong>Subscribe</strong> to changes and <strong>react</strong> to them</li></ul><h3>Advanced</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/550/1*qO5Sl7HCEelITVcs0Tuh2g.jpeg" /><figcaption>The Icing on the Cake!</figcaption></figure><h4>Detect More Expressions</h4><p>With the process above we can detect those face expressions included in the standard default set of Wink Face Expressions to be detected. But, <strong>what happens if we want to detect a gesture and it is not there?</strong> What if we want to detect when the user’s left eye is wide open? Very easy! Thanks again to the open/closed principle<strong> we can add this functionality without having to modify Wink’s code</strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7d30cfc0c356bb1d39bde048b8f60161/href">https://medium.com/media/7d30cfc0c356bb1d39bde048b8f60161/href</a></iframe><p>We create a new FacialExpressionAnalyzer with the new Wink FacialExpression , the AR BlendShapeLocation that should be detected and the minimum accepted coefficient to consider that gesture as actually happening. For a complete list of BlendShapeLocationyou can detect, or in other words, <strong>new user face expressions</strong>, please refer to the <a href="https://developer.apple.com/documentation/arkit/arfaceanchor/blendshapelocation">Apple Documentation</a>.</p><h4>Change the Minimum Valid Coefficient for a Face Expression</h4><p>Yeah, it is that easy. In the same way, we can modify the minimumValidCoefficient of the default analyzers to meet our specific requirements:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eed1b0c4c0ec5b964adb93b257c9460d/href">https://medium.com/media/eed1b0c4c0ec5b964adb93b257c9460d/href</a></iframe><p>We create a new analyzer with the expression we want to modify, assign it a new coefficient, and replace the old analyzer with the new one. In this case, we will accept a hint of a left smile (0,2/1) as valid, we feel so generous.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2K_AhxZnvWVXXCK3" /><figcaption>Photo by <a href="https://unsplash.com/@jessicarockowitz?utm_source=medium&amp;utm_medium=referral">Jessica Rockowitz</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Recap</h3><p>That’s all friends! <strong>Now you can react in your app to any user’s face expression input to develop new functional, helpful and funny features interactions.</strong> After reading this post we know:</p><ul><li>How you can <strong>detect and react to the user face expressions through Wink</strong></li><li>How can it <strong>help you</strong></li><li>How it uses <strong>ARKit to detect the Face Expressions behind the scenes</strong></li><li>How <strong>you can react to the User Face Expressions in your app</strong> using Wink</li><li>How you can extend Wink to <strong>detect more Face Expressions</strong> or change the minimum valid coefficient of one of the default ones</li></ul><p>To know more about Wink and start using it, Check here for the link to the <a href="https://github.com/toupper/Wink">GitHub Repo Page</a> You can easily integrate it with Swift Package Manager, or just dragging the source files into your project.</p><p>And of course any contribution, suggestion or question are more than welcome, either here in the comments or opening an Issue in the GitHub Repo.</p><p>Happy Winking! And remember:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/190/1*F9g2vP0RIgRir7VwkMIRLw.jpeg" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cb7634096a82" width="1" height="1" alt=""><hr><p><a href="https://medium.com/axel-springer-tech/wink-or-how-your-users-can-interact-with-your-ios-app-by-changing-their-face-expressions-cb7634096a82">Wink! Or How your Users can interact with your iOS App by changing their Face Expressions</a> was originally published in <a href="https://medium.com/axel-springer-tech">Axel Springer Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Ensure Abstraction in your iOS App Codebase when using Combine]]></title>
            <link>https://medium.com/axel-springer-tech/ensure-abstraction-in-your-ios-app-codebase-when-using-combine-6436aaccf38?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/6436aaccf38</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[combine]]></category>
            <category><![CDATA[reactive-programming]]></category>
            <category><![CDATA[clean-code]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Mon, 12 Oct 2020 13:52:29 GMT</pubDate>
            <atom:updated>2020-10-26T08:31:26.677Z</atom:updated>
            <content:encoded><![CDATA[<h3>Ensure Abstraction in your iOS Application Codebase when using Combine</h3><h4>Hide your Implementation Details to make your Code cleaner and safer</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sYa3uAAj5oygdKS2" /><figcaption>Photo by <a href="https://unsplash.com/@epicantus?utm_source=medium&amp;utm_medium=referral">Daria Nepriakhina</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Our iOS Team at WELT got recently very good news, we could <strong>set our App iOS Deployment Target to 13.0</strong>. That means not only that we should not support old versions anymore, but also that we can start using the cool APIs that were introduced in that version, especially <strong>SwiftUI </strong>and<strong> Combine</strong>.</p><p>With <a href="https://developer.apple.com/documentation/combine">Combine</a> we can write <strong>functional reactive code</strong> to process values over time through a <strong>declarative Swift API</strong>. It can be compared to other takes on this approach for Swift, such as <a href="https://github.com/ReactiveX/RxSwift">RxSwift</a> and <a href="https://github.com/ReactiveCocoa/ReactiveSwift">ReactiveSwift</a>.</p><blockquote><strong>Tip:</strong> If your app still cannot fully support Combine because the minimum deployment target is lower than iOS 13.0 don’t worry, you can start migrating it by using <a href="https://github.com/OpenCombine/OpenCombine">OpenCombine</a>. According to their <a href="https://github.com/OpenCombine/OpenCombine#opencombine">docs</a>:<br>The main goal of this project is to provide a compatible, reliable and efficient implementation which can be used on Apple’s operating systems before macOS 10.15 and iOS 13, as well as Linux and Windows.</blockquote><blockquote>That way, given that their API is exactly the same as Combine, it will ease the migration process to Combine in the future; ideally you will just have to replaceimport OpenCombine with import Combine.</blockquote><p>Coming back to Combine, for now two concepts are essential for those familiar with the RxSwift syntax or similar:</p><ul><li>Observables are Publishers in Combine. They <strong>expose</strong> values that can change.</li><li>Observers are Subscribers in Combine. They <strong>subscribe</strong> to receive all these updates.</li></ul><p>With this in mind, let’s see one example where we can use it.</p><h3>Combine and MVVM</h3><p>Combine, as any other reactive framework, is especially adequate to implement a <a href="https://www.raywenderlich.com/34-design-patterns-by-tutorials-mvvm#:~:text=Model%2DView%2DViewModel%20(MVVM,re%20typically%20subclasses%20of%20UIView%20.">MVVM</a> architecture: the View Model encapsulates the processing and exposes the UI data, that can change over time. The View subscribes to the View Model to receive these updates and react accordingly, refreshing the UI and showing the new values to the user. Together with all the chaining operators that the reactive frameworks provide, it makes the code more declarative and thus readable.</p><p>In this example, we want to show the user a sport event result. <strong>As it changes over time</strong>, reactive programming is ideal for our case.</p><p>The first version of our ResultViewModel with Combine would be something like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/810803c85af57232c9e185329237e347/href">https://medium.com/media/810803c85af57232c9e185329237e347/href</a></iframe><p>Our View Model listens to the result updates from the fetcher implementing the delegate method, used for simplicity sake in our example (we could very well be using reactive programming in this layer as well). Once a new result has arrived, we use a <a href="https://developer.apple.com/documentation/combine/passthroughsubject">PassthroughSubject</a> that <strong>broadcasts new data to downstream subscribers</strong>, in this case the view, so it can accordingly refresh the UI:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7b10dc12749e885197ea9013fd6a17a1/href">https://medium.com/media/7b10dc12749e885197ea9013fd6a17a1/href</a></iframe><p>Here, we subscribe to the View Model updates on the result, react refreshing the label when a new value is received always on the main thread, and store the AnyCancellable object in a Set, so we do not lose the reference.</p><h3>Abstraction!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*f5qZShP218T4x2_7" /><figcaption>Photo by <a href="https://unsplash.com/@korpa?utm_source=medium&amp;utm_medium=referral">Jr Korpa</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>The example above works fine, we are implementing the business logic as required: every time the result changes it is reflected in the UI. But correct as it is, the code is still very faulty.</p><p>Why? because <strong>with </strong><strong>PassthroughSubject we are exposing the implementation details of our operation</strong>. That is bad by reason of generating a dependance between the client, in this case the View, and the implementation, making it easy to break by any change or modification in the latter. Imagine for instance that the View Model needs to keep a buffer of the most recently published element for tracking purposes. In that case we cannot use the PassthroughSubject, but <a href="https://developer.apple.com/documentation/combine/currentvaluesubject">CurrentValueSubject</a> instead. The View Model API will change.</p><p>But more importantly, with PassthroughSubject, <strong>we give the power to the view to send events through it</strong>, something that is clearly not its task. It should just listen, not update it. <strong>Our code isn’t safe</strong>.</p><p>This is when AnyPublisher comes on the scene. According to the Apple docs:</p><blockquote>Use <a href="https://developer.apple.com/documentation/combine/anypublisher">AnyPublisher</a><strong> to wrap a publisher whose type has details you don’t want to expose across API boundaries, such as different modules. Wrapping a </strong><a href="https://developer.apple.com/documentation/combine/subject"><strong>Subject</strong></a><strong> with </strong><a href="https://developer.apple.com/documentation/combine/anypublisher"><strong>AnyPublisher</strong></a><strong> also prevents callers from accessing its </strong><a href="https://developer.apple.com/documentation/combine/subject/send(_:)"><strong>send(_:)</strong></a><strong> method. </strong>When you use type erasure this way, you can change the underlying publisher implementation over time without affecting existing clients.</blockquote><p>This is exactly what we want:</p><ul><li><strong>Hide type details</strong></li><li>Prevent callers <strong>from accessing</strong><strong> send(_:)</strong></li><li>Be able to change the publisher implementation over time <strong>without affecting clients</strong></li></ul><p>Oh, but wait, we can still push it a little bit forward into the Abstraction Realm right? We can create a protocol for the View Model, thus hiding more details (the Data Fetcher for instance) and enhancing testability by replacing it easily with a mock when unit testing it. For more info about Protocol-Oriented Programming in Swift, check this <a href="https://www.raywenderlich.com/6742901-protocol-oriented-programming-tutorial-in-swift-5-1-getting-started">link</a>.</p><p>Consequently, we can already implement our new version of the View Model:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c845eb257ae924c7c060b671375a6938/href">https://medium.com/media/c845eb257ae924c7c060b671375a6938/href</a></iframe><p>This way we are just exposing an AnyPublisher object, so the clients can subscribe but not update as intended. With <a href="https://developer.apple.com/documentation/combine/publisher/erasetoanypublisher()">eraseToAnyPublisher()</a> we achieve exactly that, to expose an instance of AnyPublisher to the downstream subscriber rather than this publisher’s actual type, an action that we call <a href="https://www.swiftbysundell.com/articles/different-flavors-of-type-erasure-in-swift/"><strong>Type Erasure</strong></a>: we hide implementation details by exposing a more abstract type, a technique that can be applied thanks to <strong>polymorphism</strong>. Now the View has the right access level to the Publisher.</p><h3>Another Turn on The Screw?</h3><p>As Henry Miller in his superb <a href="https://www.goodreads.com/book/show/12948.The_Turn_of_the_Screw">novella</a>, you might still want to push it a little bit forward. Why not using <a href="https://developer.apple.com/documentation/combine/publisher">Publisher</a> instead of AnyPublisher? Isn’t it even more abstract? At least it sounds so …</p><p>The answer is no, Publisher and AnyPublisher are different things, with different purposes:<strong> with </strong><strong>Publisher we cannot achieve Type Erasure as with </strong><strong>AnyPublisher</strong>. The former is a protocol with <a href="https://www.hackingwithswift.com/example-code/language/what-is-a-protocol-associated-type">associated types</a>, therefore it can be used when you define a function that has generics as part of the definition, such as a Protocol Extension, e.g. when creating a custom Combine operator. An example from <a href="https://stackoverflow.com/a/59043496/428353">here</a>:</p><p>extension Publisher {<br> public func compactMapEach&lt;T, U&gt;(_ transform: @escaping (T) -&gt; U?)<br> -&gt; Publishers.Map&lt;Self, [U]&gt;<br> where Output == [T]<br> {<br> return map { $0.compactMap(transform) }<br> }<br>}</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PksDELJ-Z2F_RxuD" /><figcaption>Photo by <a href="https://unsplash.com/@purzlbaum?utm_source=medium&amp;utm_medium=referral">🇨🇭 Claudio Schwarz | @purzlbaum</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Conclusion</h3><p>Now that iOS 14 is released, it is more likely that you will be able to drop older iOS version, thus being able to migrate to (or start using) Combine. When doing that, we should as always be conscious of writing a <strong>readable, maintainable and safe code that uses Abstraction when possible</strong>. Apple goes in the same direction, and adds Type Erasure to our toolset. There is no excuse to avoid ensuring Abstraction when writing your implementation with Combine.</p><p>To recapitulate, in this article we have seen:</p><ul><li>How we can ease the future reactive migration process to Combine <strong>by using OpenCombine with earlier iOS versions</strong></li><li>How we can use Combine to implement a <strong>simple MVVM solution</strong></li><li>How we can support <strong>Abstraction and Protocol-Oriented Programming </strong>with Combine</li><li>Why we cannot use <strong>Publisher</strong> in the place of <strong>AnyPublisher</strong></li></ul><p>I would like to thank my colleague <a href="https://github.com/ivanlisovyi">Ivan Lisovyi</a> for his splendid insight and contribution about this topic, without which this story would not have been possible. As always, if you have a question or contribution please drop a message below.</p><p>Happy Abstraction!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6436aaccf38" width="1" height="1" alt=""><hr><p><a href="https://medium.com/axel-springer-tech/ensure-abstraction-in-your-ios-app-codebase-when-using-combine-6436aaccf38">Ensure Abstraction in your iOS App Codebase when using Combine</a> was originally published in <a href="https://medium.com/axel-springer-tech">Axel Springer Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jekyll & Netlify: A Web Love Story]]></title>
            <link>https://medium.com/swlh/jekyll-netlify-a-web-love-story-6ab13dd324e9?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/6ab13dd324e9</guid>
            <category><![CDATA[css]]></category>
            <category><![CDATA[netlify]]></category>
            <category><![CDATA[web-design]]></category>
            <category><![CDATA[jekyll]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Thu, 13 Aug 2020 09:10:50 GMT</pubDate>
            <atom:updated>2020-12-16T14:30:16.855Z</atom:updated>
            <content:encoded><![CDATA[<h4>Create your own website without taking a sweat</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/900/1*MVavrPv0pAbUlfrb7IggHw.jpeg" /></figure><p>Today I’ll cover a different topic than usual. In fact, i am not going to mention the word <em>Swift</em> (oops, just did) or iOS in the whole article. On this occasion I will talk about a personal project I developed while enjoying my summer holidays in the south of Spain: <a href="https://cesarvargas.es"><strong>my personal website</strong></a>.</p><h3>Why a personal website?</h3><p>To be honest, the main reason why I created <a href="https://cesarvargas.es"><strong>my own website</strong></a> was to learn the technologies involved in the process. We as mobile developers sometimes see the web and its environment as something obscure and arcane. <strong>Nothing further from the truth</strong>. As we are going to see, the development of a simple and good looking web page is a <strong>very straightforward process</strong>, given the cool technologies we can use.</p><p>On top of that, as a Software Developer, having your own website is a perfect scenario to showcase your skills, projects, and experience at one single place. If not your personal website, you can choose to create something less egotist as a blog focusing on your area of expertise. These are popping up like mushrooms these days, <a href="https://www.avanderlee.com/">some of them</a> really well curated and visually pleasant.</p><h3>What do we need?</h3><p>Once we know <strong>what</strong> (a simple personal website) and <strong>why</strong> (to learn, to enhance my professional image), we need the <strong>how</strong>, and as Nietzsche suggested,</p><blockquote>“He who has a why can bear almost any how”.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*taHdnEimTrOmEs-h2Hbs9w.jpeg" /><figcaption>Nietzsche is pointing us the way</figcaption></figure><p>So in order to successfully achieve our task, we need three steps:</p><ul><li>A <strong>Domain</strong></li><li>The <strong>Website</strong> itself</li><li>A <strong>Hosting</strong> Service</li></ul><h3>The Domain</h3><p>Even if that is not necessarily the first step in chronological order, it is allegedly the most exciting, <strong>envisioning your own website URL in the browser address bar</strong>.</p><p>The domain name should be <strong>simple and short</strong>, avoiding double or special characters, such as dashes and hyphens. If you do not have the misfortune of sharing your name with a popular baseball player as in my case <strong>you should stick to .com as top-level domain</strong>, otherwise I would go with your country one, or something easy to remember. In my case, it was my name + surname + country top-level domain: <a href="https://cesarvargas.es">cesarvargas.es</a>: short, <em>catchy</em> and memorable. Of course, all these tips are very good but we depend on the domain availability: it could be taken, or cost a large sum of money:</p><blockquote><strong>“Everybody has</strong> a <strong>plan until they get</strong> punched in the mouth.” Mike Tyson</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SCr1dyjbUa8xs9aJ" /><figcaption>Photo by <a href="https://unsplash.com/@bayleejadegramling?utm_source=medium&amp;utm_medium=referral">Baylee Gramling</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Once we dodged that punch and came up with an available domain name we should purchase it promptly, before our best <a href="https://www.urbandictionary.com/define.php?term=Frenemy">frenemy</a> does it.</p><p>There are nowadays many Internet domain registrar companies with similar services, I went for <a href="http://godaddy.com">GoDaddy</a> because already had an account. It is allegedly the largest domain provider, with its simplicity and pricing as their largest strengths. The cheap prices can be deceiving though, as they would charge for something as simple as privacy. On top of that, be ready for a ton of spam if you are not renewing your domain and their continuous tries to upsell you.</p><p>In the other hand, if you feel brave and want something more powerful, you should take a look at <a href="https://domains.google/">Google Domains</a> or <a href="https://aws.amazon.com/en/route53/">Amazon Route 53</a></p><h3>The Page</h3><p>Once we have a domain, it is time to develop the website itself. As you may suspect this is the longest task but do not fear, in our case it will be uncomplicated.</p><p>As far as we are concerned, we just need something <strong>simple</strong>. It will show the <strong>same content</strong> to all users and all contexts. It will <strong>rarely change</strong>, maybe we will edit our bio or project texts but once performed, it will be very stable. Oh wait, we just defined a <strong>static website</strong>!</p><blockquote>A <strong>static web page</strong> (sometimes called a <strong>flat page</strong> or a <strong>stationary page</strong>) is a <a href="https://en.wikipedia.org/wiki/Web_page">web page</a> that is delivered to the user’s web <a href="https://en.wikipedia.org/wiki/Web_browser">browser</a> exactly as stored, in contrast to <a href="https://en.wikipedia.org/wiki/Dynamic_web_page">dynamic web pages</a> which are generated by a web application.</blockquote><blockquote>Consequently, a static web page displays the same information for all users, from all contexts, subject to modern capabilities of a <a href="https://en.wikipedia.org/wiki/Web_server">web server</a> to <a href="https://en.wikipedia.org/wiki/Content_negotiation">negotiate</a> <a href="https://en.wikipedia.org/wiki/MIME_type">content-type</a> or language of the document where such versions are available and the <a href="https://en.wikipedia.org/wiki/Server_(computing)">server</a> is configured to do so. Wikipedia</blockquote><p>So, what are the advantages of a static web page compared to a more dynamic web application?:</p><ul><li>It is <strong>safer</strong>, being so simple it has fewer vulnerabilities.</li><li>More performant, <strong>faster</strong>.</li><li><strong>Fewer</strong> dependencies, no databases, no CMS. Fewer headaches.</li><li><strong>Cheaper</strong>, we just need a cloud storage.</li></ul><p>Of course, dynamic web applications are a must if we want something more complex, with queries and other dynamic functionality, but given that we do not need that, <strong>we can safely go for a static one</strong>. The biggest restriction we have is that any personalization or interactivity has to run client-side, which can be cumbersome. But again, that is not something we should worry about here.</p><p>Yes! we want a static website, and we will accept any external help to achieve our task. We will make use of <a href="https://jekyllrb.com/">Jekyll</a>. According to their <a href="https://github.com/jekyll/jekyll">repo</a>, <em>Jekyll </em><strong><em>is a simple, blog-aware, static site generator perfect for personal, project, or organization sites</em></strong><em>. Think of it like a file-based CMS, without all the complexity. Jekyll takes your content, renders Markdown and Liquid templates, and spits out a complete, static website ready to be served by Apache, Nginx or another web server. Jekyll is the engine behind </em><a href="https://pages.github.com/"><em>GitHub Pages</em></a><em>, which you can use to host sites right from your GitHub repositories.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/512/1*SIkjQ8aDsxYhy79HYrzdow.png" /><figcaption>No, not that Jekyll</figcaption></figure><p>It was recommended to me for <strong>its simplicity and ease of configuration</strong>. Furthermore, as we will see, it is well known and supported in the community, where you can find free and paid templates that match your case.</p><p>So, once we have the technology, we need the most important part, the <strong>content</strong>. And again, in search of simplicity, we will download a template and adapt it to our requirements instead of creating it ourselves. Take a look at <a href="https://jekyllrb.com/resources/">Jekyll Resources</a>, where you can find a handsome case that matches your scenario. But we should not constrain ourselves only to a preset Jekyll Theme, if we already have an HTML site we can easily convert it to Jekyll following the process described in this <a href="https://jekyllrb.com/tutorials/convert-site-to-jekyll/">article</a>.</p><p>Alright! We have a theme, but the content is not personalized for our story, we should add our information so our moms can proudly show it to relatives and friends. And here it is where the perks of Jekyll come to shine. If the template was flexible enough, the content is easily customizable by adding the visible properties defined in the _config.yml A ton of HTML or CSS variable are defined there, together other main predefined <a href="https://jekyllrb.com/docs/variables/">ones</a></p><pre># Site settings<br>title: César Vargas Casaseca<br>url: <a href="https://cesarvargas.es">https://cesarvargas.es</a></pre><pre># Google webmaster tools<br>google_verify:</pre><pre># Color settings (hex-codes without the leading hash-tag)<br>color:<br> primary: 0d0c0c #80B3FF<br> primary-rgb: “255,70,49” #”128,179,255&quot;</pre><pre>#texts<br>main: This is a just a text to be shown in our awesome website</pre><p>And if we want to add <strong>more flexibility</strong> to our project by including other <strong>customizable elements</strong>, we can just add it to the relevant file using the template language <a href="https://jekyllrb.com/docs/liquid/"><strong>Liquid</strong></a>. Jekyll will then traverse the files looking for something to process. Take a look <a href="https://jekyllrb.com/docs/variables/">here</a> and <a href="https://jekyllrb.com/docs/front-matter/">here</a> for more information.</p><p>Summing up this step a bit, in order to achieve a static website with Jekyll we have to:</p><ul><li>Download and install <strong>Jekyll</strong></li><li>Download a Jekyll Template theme, or convert any other HTML one to Jekyll</li><li>Customize it by adding your wished variables or creating new ones. Adjust texts, colors and other elements</li></ul><h3>The Hosting</h3><p>Nice! We have a super fancy website that runs smoothly … locally, on our computer. The next step is to host it externally, so it can be accessed everywhere. And we want to do it easily and cheaply, without a strenuous process to deploy or expensive tiers for just hosting a static webpage. Besides that, it should blend effortlessly with Jekyll, and be able to set the domain from an external provider without further endeavour.</p><p>The answer to all our wishes is <a href="https://www.netlify.com/"><strong>Netlify</strong></a>. <strong>Netlify is a cloud computing company that offers hosting and server less back end services for static websites.</strong> It features <strong>continuous deployment</strong> from Git across a global application delivery network, server less form handling, support for AWS Lambda functions, and full integration with Let’s Encrypt.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IFlr9JVFIgYoQ0RxUZnzHw.png" /></figure><p>It is <strong>free</strong> for our case, the UI is very <strong>intuitive</strong> and <strong>deployments are rapid</strong>. As I mentioned above, the deployments are to be done with Git, so if you did not do it before, <strong>we should store our project into a GitHub repository</strong>. Once we’ve done that, we can login to Netlify with our GitHub account and specify that everytime we push to master the webpage is deployed. It is that easy! Furthermore, it supports Jekyll very smoothly, <strong>we just have to add our Build command </strong><strong>jekyll build in the Build Settings</strong>. You can get to know more about how Jekyll is integrated with Netlify in this interesting <a href="https://www.netlify.com/blog/2020/04/02/a-step-by-step-guide-jekyll-4.0-on-netlify/">post</a>.</p><p>And finally we just need to <strong>connect our domain</strong> with the hosted website in Netlify. For the purpose of using Netlify DNS, we are going to change the domain names in GoDaddy or any other domain provider to the custom hostnames assigned to your DNS zone in Netlify. It can take a maximum 24 hours to complete this task depending on the registrar. Once it is finished, your domain will be pointing to your hosted website in Netlify and will be available everywhere. So, in order to host your web in Netlify …</p><ul><li>Login to Netlify with your <strong>GitHub account</strong></li><li>Host your webpage project in a <strong>GitHub Repo</strong></li><li>Specify your website GitHub Repo in your Netlify Settings</li><li>Add the Build Command in Build settings, in our case jekyll build</li><li>Push to master (or any other specified branch) to <strong>deploy</strong></li><li>Connect your domain to your <strong>Netlify DNS</strong> zone</li></ul><h3>The Icing on the Cake</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*e78uWwWE-toxTd-P" /><figcaption>Photo by <a href="https://unsplash.com/@americanheritagechocolate?utm_source=medium&amp;utm_medium=referral">American Heritage Chocolate</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>With that you should now have your own website up and running, accessible through your domain from anywhere in the world. At that moment I still felt brave enough to try to improve it a little bit. For instance, I registered my website in <a href="https://search.google.com/search-console/about">Google Search Console</a>. Search Console tools and reports help you measure your site’s <strong>Search traffic and performance</strong>, fix issues and make your site shine in Google Search results. You can do the same with <a href="https://www.bing.com/toolbox/webmaster">Bing</a>, or any other SEO tools that you might find convenient. Do not forget, our goal was to learn, play and have fun, and these tools are a warranty for that.</p><p>In addition, our product would feel orphan without a proper way to track its traffic and activity. <a href="https://analytics.google.com/analytics/web/provision/#/provision">Google Analytics</a> is the most widely used website statistics service, but there are others such as <a href="https://matomo.org/">Matomo</a> or <a href="https://www.woopra.com/">Woopra</a>, with a bigger emphasis on privacy or easiness of usage.</p><p>And if you feel like you could earn some nickels monetizing your website, you can display some ads on it. Take a look at <a href="https://www.google.com/adsense/start/">Google AdSense</a> for an easy ad integration. In short, if we want to improve our web, we could …</p><ul><li>Enhance our <strong>SEO</strong> with Google Search Console or Bing Webmaster Tools</li><li><strong>Track</strong> our traffic and activity with an Analytics tool, such as Google Analytics</li><li><strong>Monetize</strong> our content displaying Ads</li></ul><h3>Conclusion</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XHR1nobbcMCuuLKevqvMlQ.png" /></figure><p>In this post we have learned that basic web development <em>should not be difficult</em>. We have seen the <strong>differences</strong> between <strong>static and dynamic websites</strong>, and when to use each of them. We picked up contrasted tool for each step along the process, and described ways to refine our project learning new technologies and products.</p><p>As always, if you have any suggestion please drop a message or a margin note. Here you can see my final outcome: <a href="https://cesarvargas.es">https://cesarvargas.es</a></p><p>Happy web creating!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ab13dd324e9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/jekyll-netlify-a-web-love-story-6ab13dd324e9">Jekyll &amp; Netlify: A Web Love Story</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Common Reuse Principle on iOS]]></title>
            <link>https://medium.com/axel-springer-tech/the-common-reuse-principle-on-ios-f4b7b1b945a3?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/f4b7b1b945a3</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[clean-architecture]]></category>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Sun, 21 Jun 2020 09:01:57 GMT</pubDate>
            <atom:updated>2020-06-24T11:54:31.542Z</atom:updated>
            <content:encoded><![CDATA[<h4>Bear this in mind before creating or adding a 3rd Party Library to your project</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/992/1*jkdb2HQoJf-EAJbAQ-MpOg.jpeg" /><figcaption>So many things we do not need!</figcaption></figure><p>We as developers are usually advised to search in the Open Source Community before adding new functionality. The odds are that most likely some other engineer faced the same problem and, in a remarkable act of charity, published their solution so we can also reuse it. Or perhaps we are that caring developer, who content with their work, decided that more people should benefit from it.</p><p>In any case, we should make sure that the component will adhere to the Common Reuse Principle (CRP): <em>Don’t force users of a component to depend on things they don’t need. </em>Oh ok, could you elaborate on that? Yeah, sure.</p><h3>The CRP in Depth</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*H-5bHjsdA5LlM1hS" /><figcaption>Photo by <a href="https://unsplash.com/@nervum?utm_source=medium&amp;utm_medium=referral">Jack B</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Whenever we have a use case, some set of classes collaborate amongst themselves to achieve their goal. A very common case is a Factory class and the types it generates, they are tightly coupled. Being so dependant on each other, the CRP states that they belong together in the same component.</p><blockquote><strong>Classes and modules that tend to be reused together belong in the same component</strong>.</blockquote><p>Until here everything is fine, if this is the case of our analysed component we should not worry. The issue arises when we flip the coin and state the principle inversely; it provides us even more valuable information. It tells us which classes should not be kept together in a component: <strong>those that are not reused together.</strong></p><h3>Why Not?</h3><p>Because once we are using another component, we have a dependency <strong>for the whole component, for all the classes</strong>. Yeah, maybe we are only using one class of it, but still we are going to suffer all the inconvenience of a big dependency:</p><ul><li>Every time that component changes we will need corresponding changes.</li><li>Or maybe they keep a clean interface so no changes in our side are required, but for sure we are going to have to compile <strong>the whole component </strong>again and again.</li></ul><p>The latter was the major drawback for us at <a href="https://www.welt.de/">WELT</a>, especially when compiling on a slower machine, as the virtual ones assigned in a remote based CI solution.</p><h3>An Example</h3><p>In <a href="https://apps.apple.com/de/app/welt-news-nachrichten-live/id340021100">WELT News</a> we convert the HTML text into NSAttributedString to be displayed in our Articles Views. At first we tried the built-in framework to carry out this operation, having something like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c16e907832de0f681e32822c6389fd1c/href">https://medium.com/media/c16e907832de0f681e32822c6389fd1c/href</a></iframe><p>And it worked fine, but unfortunately very slow. Moreover, since the execution should be performed on the main thread, the UI was blocked until it finished, which was not acceptable for our stakeholders.</p><p>Luckily we got to know <a href="https://github.com/Cocoanetics/DTCoreText">DTCoreText</a>, a project that duplicates the Apple method, only doing it <a href="https://stackoverflow.com/questions/28421816/is-there-a-way-to-speed-up-html-to-nsattributedstring-rendering-in-ios-8"><strong>18x times faster</strong></a><strong>. </strong>We were very happy with that approach, so we decided to integrate it in our library.</p><p>The dilemma popped up when realizing that DTCoreText uses <a href="https://github.com/Cocoanetics/DTFoundation">DTFoundation</a> behind the scenes, <em>a collection of utility methods and category extensions that Cocoanetics is standardizing on.</em></p><p>So DTFoundation includes a lot of classes that are not related to our use case. Just to render our text faster we have to compile classes related to a large variety of topics such as SQLite, ZIP files, AWS …</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/630/1*E-H9j_ZEfg-a60fjyb7EEw.png" /><figcaption>We depend on tons of things we do not need</figcaption></figure><p>Even if these components might eventually be useful to us, we are currently not using them, and therefore shouldn’t have to include them. We should not compile them in our project, as it will slow build times.</p><p>We might argue that these frameworks will only be built once, since every dependency manager and CI will enable us to cache and reuse them. Even with that, it is worth to decrease the compilation times for that first time, or cut down the size of the cache. On top of that, if the component is updated because of an unrelated change and we are always up to date with our dependencies, it will compile every time it needs to update.</p><h3>The Solution</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2S4EC4Ec9U48Jrw9" /><figcaption>Photo by <a href="https://unsplash.com/@olav_ahrens?utm_source=medium&amp;utm_medium=referral">Olav Ahrens Røtne</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>The CRP tells us that when we depend on a component, we should aspire to <strong>depend on every class in that component. </strong>As Robert C Martin points in <a href="https://www.amazon.com/-/de/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164/ref=sr_1_1?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;crid=ZF6H05BURVDX&amp;dchild=1&amp;keywords=clean+architecture&amp;qid=1592728862&amp;sprefix=clean+archi%2Caps%2C239&amp;sr=8-1">Clean Architecture</a>, <em>we want to make sure that the classes we put in a component are inseparable- that it is impossible to depend on some and not on the others.</em></p><p>In other words, classes that are not tightly bound to each other should not be in the same component. That goes against the Umbrella Toolset libraries that contains big collections of utilities applied to a big number of different topics.</p><p>To avoid the caveats mentioned above, we plan to extract the classes reused together to achieve the use case of HTML conversion into NSAttributedString into their own component. This way <strong>we will only have to compile the necessary number of classes reused together to achieve our goal.</strong></p><h3>Its first cousin, the ISP</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OzwARbvHUg1RlZ7LYyLCrg.png" /></figure><p>This probably all sounds very familiar to you. Most likely it reminds you of the <strong>Interface Segregation Principle, </strong>the <strong>I</strong> from <strong>SOLID:</strong></p><p><em>Clients should not be forced to depend upon interfaces that they do not use.</em></p><blockquote>Indeed, the ISP advises us <em>not to depend on classes that have methods we don’t use</em>, the CRP advises us<em> not to depend on components that have classes we don’t use</em>. The foundation behind them is the same:</blockquote><h3><strong><em>Don’t depend on things you don’t need!</em></strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/896/1*pogUGuqzDOROqPiMRAu2ZA.png" /><figcaption>The Death of Socrates, Jacques-Louis David</figcaption></figure><p>We are usually told, <a href="https://softwareengineering.stackexchange.com/questions/29513/is-reinventing-the-wheel-really-all-that-bad">don’t reinvent the wheel</a>. And rightly so. If there is already a proven open source solution to our problem which is backed up by a large community of users, it would serve us well to use it.</p><p>But before adding the dependency blindly to our codebase, we should stop and analyze the component, to make sure that we are not going to be dependant on things we do not need. This will give us time, and time is our most valuable asset.</p><p>So, just as when <a href="https://www.youtube.com/watch?v=BvYRqsRZ7vE">Socrates</a> strode through the city’s central marketplace and declared provocatively, “How many things I don’t need!”, we should, in our life as in our code, confidently assert:</p><p><strong><em>Don’t depend on things you don’t need!</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f4b7b1b945a3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/axel-springer-tech/the-common-reuse-principle-on-ios-f4b7b1b945a3">The Common Reuse Principle on iOS</a> was originally published in <a href="https://medium.com/axel-springer-tech">Axel Springer Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Acyclic Dependencies Principle on iOS]]></title>
            <link>https://medium.com/axel-springer-tech/the-acyclic-dependencies-principle-on-ios-7804e6b1bbf9?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/7804e6b1bbf9</guid>
            <category><![CDATA[ios-development]]></category>
            <category><![CDATA[monolithic]]></category>
            <category><![CDATA[clean-architecture]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[abstraction]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Fri, 22 May 2020 10:40:46 GMT</pubDate>
            <atom:updated>2020-05-27T18:47:17.294Z</atom:updated>
            <content:encoded><![CDATA[<h4>Or how to avoid Merging Nightmares and Long Compilation Times</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/752/1*pkBsF0HMi-POnzOkyx0-JQ.png" /></figure><p>More and more we see how the iOS community strives for more <a href="https://medium.com/swlh/modularize-an-ios-application-919b30e41e3c"><strong>modularized architectures</strong></a>. And it is obviously not just a fad. The benefits are clearly evident, the most immediate being <strong>much shorter compilation times </strong>given that you can just focus on the working framework. Furthermore, you are aiming for a cleaner architecture, one much more readable and testable. On top of that, you can just reuse your component in any other application, or exchange it as you wish.</p><p>But same as when creating your object oriented design you rely on the <a href="https://scotch.io/bar-talk/s-o-l-i-d-the-first-five-principles-of-object-oriented-design">SOLID</a> principles to make it easy to maintain and extend, when constructing your components architecture you always must bear in mind these three points:</p><ul><li><strong>APD</strong>: The Acyclic Dependencies Principle</li><li><strong>SDP</strong>: The Stable Dependencies Principle</li><li><strong>SAP</strong>: The Stable Abstractions Principle</li></ul><p>In this first article we will focus on the ADP, <strong>The Acyclic Dependencies Principle.</strong></p><h3>The Acyclic Dependencies Principle</h3><p><em>Allow no cycle in the component dependency graph</em></p><p>The theory is simple, our dependency graph should not contain any cycle. If there is one cycle, we are just creating a big monolithic component causing exactly what we wanted to avoid in the first place: longer compilation times and other effects caused by a highly coupled architecture, such as the <a href="https://www.blazent.com/the-morning-after-syndrome/">morning after syndrome</a>. How can we avoid that? Let’s look at an example on iOS with the <a href="https://medium.com/better-programming/mvvm-in-ios-from-net-perspective-580eb7f4f129">MVVM</a> architecture.</p><h4>An Acyclic Dependency Architecture</h4><p>Let’s suppose that we modularized the architecture of an IOS application that uses <strong>MMVM</strong>. Model-View-ViewModel (<strong>MVVM</strong>) is a structural design pattern that separates objects into three distinct groups: Models, Views and ViewModels. Because we are super impressed with the benefits stated above, we are going to create a <a href="https://www.raywenderlich.com/5109-creating-a-framework-for-ios"><strong>Framework</strong></a> for each of them.</p><p>Our application is simple, the UI will display distinctive elements depending of the User Permissions in the User Profile, and it will be the responsibility of the ViewModel to discern what to show:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*trbzYxgB8HXpr6P8zryLhg.jpeg" /></figure><p>This is a directed graph, we can follow the dependencies with the arrows. Moreover, there are no cycles in it, it is a Directed Acyclic Graph (DAG). It is awesome.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_30xAPmwHdhGQA_l" /><figcaption>Photo by <a href="https://unsplash.com/@jontyson?utm_source=medium&amp;utm_medium=referral">Jon Tyson</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Here we have 4 components, obviating the View or some Routing layer that are not relevant for our case. The <strong>UserProfileViewModel</strong> depends on the <strong>User</strong> struct in the Model to get the information. This one at the same time depends on the <strong>PermissionsManager</strong> to enrich its data with its given permissions.</p><h3>The Misdeed</h3><p>Now, the Interaction Designer has come to us with a new feature, we will show a totally different view depending on the User Permissions. That way, they will sell more subscriptions because we show more promotional content directed to a non-paying user.</p><p>Once they let us know this new task, it is time to design our approach. We will create a Factory class that will provide the right View Model depending on the User Permissions. After some deliberation, the “expert” in our team decides that it should be included in the Permissions Manager framework, given that everything related to the permissions is its responsibility. (please forgive this atrocious architecture).</p><p>Alright, so it is! The factory is implemented in the PermissionsManager, and our architecture looks like this now:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*fBVzJDRkVai3umwHMGip8Q.jpeg" /></figure><p>We do not have an acyclic graph anymore, <strong>there is a cycle between ViewModel, Model, and PermissionsManager</strong>. We are doomed! Instead of three components, we have a big one that should be compiled entirely every time we modify any of them. Besides, given the tight coupling, one change might have consequences in any of them. Not good. Actually awful.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bwB7Swf1WqhPvBt_" /><figcaption>Photo by <a href="https://unsplash.com/@open_photo_js?utm_source=medium&amp;utm_medium=referral">Jasmin Sessler</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Break it!</h3><p>Once we are aware of the dreadful consequences of the last addition,<strong> it is time to break the cycle</strong>. To accomplish that we have two different strategies:</p><h4><a href="https://deviq.com/dependency-inversion-principle/"><strong>Apply the Dependency Inversion Principle (DIP)</strong></a></h4><p><em>Depend on abstractions, not concretions, you asshole.</em></p><p>We will create a protocol revealing the functions that provides the Permissions to the User Model. The Permissions Manager will implement that protocol, but will be hidden to the model, thus inverting the dependency between the Model and the PermissionsManager:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/366/1*1uSS-_FFE1gctmw42eob6Q.jpeg" /></figure><blockquote>It might look odd having a component with only a protocol on it and no executable code, but this is a necessary and common practice in other languages such as Java and C#. Robert C. Martin, Clean Architecture.</blockquote><h4>Create a component between them.</h4><p>To break it, we could create a component between the ViewModel and the PermissionsManager. The ViewModelFactory depends on both ViewModel and PermissionsManager, hence breaking the previous cycle:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/266/1*wsLZXAHmenDD6NhiOQOI_g.jpeg" /></figure><p>You can combine both strategies to end up with the cleanest approach, one that ensures you a good maintainability and flexibility when adding new features to the project.</p><h3>Wrapping it up</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qqf3PzV6weD-JdQ-" /><figcaption>Photo by <a href="https://unsplash.com/@joshrako?utm_source=medium&amp;utm_medium=referral">Josh Rakower</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Now that modularizing our apps is in vogue and with good reason, we should be aware that before adding new components we have to stop and think. Are we improving our architecture? Are we actually achieving the goals we strive for with our separate modules? Or are we just having the same monolithic structure although with fancier looks? We should be open to this reflection not only at design time, but also when refactoring the current solution if it shows the most common pitfalls of a non-clean architecture.</p><p>If you want to know more, I refer you to the bible on these matters, <a href="https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164">Clean Architecture: A Craftsman’s Guide to Software Structure and Design (Robert C Martin)</a> There you will find more examples about this and the other principles I mentioned above.</p><p>And of course, in case you have more questions or suggestions please drop a comment below or send me a message.</p><p>Break the cycle, man!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7804e6b1bbf9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/axel-springer-tech/the-acyclic-dependencies-principle-on-ios-7804e6b1bbf9">The Acyclic Dependencies Principle on iOS</a> was originally published in <a href="https://medium.com/axel-springer-tech">Axel Springer Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Warhol II: Compose your Overlay on Top of the Detected Face Hassle-Free for iOS]]></title>
            <link>https://medium.com/swlh/warhol-ii-compose-your-overlay-on-top-of-the-detected-face-hassle-free-for-ios-ae5b8d40924d?source=rss-c2f877dba4d------2</link>
            <guid isPermaLink="false">https://medium.com/p/ae5b8d40924d</guid>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[facedetection]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[César Vargas Casaseca]]></dc:creator>
            <pubDate>Sun, 10 May 2020 10:56:21 GMT</pubDate>
            <atom:updated>2020-05-13T08:57:30.363Z</atom:updated>
            <content:encoded><![CDATA[<h3>Warhol II: Compose your Overlay on Top of the Detected Face Hassle-Free on iOS</h3><h4>Add your Filter Overlay without having to deal with coordinates in <a href="https://github.com/toupper/Warhol">Warhol</a></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*UP1C-TmAJOzYvDdt9w6JaQ.png" /></figure><p>Some time ago I talked about <a href="https://medium.com/better-programming/warhol-face-detection-made-easy-on-ios-4b146b87b7d0">Warhol</a>, a library of my own that detects a Face from a Camera or Image input and passes the related information to the client. That way, the latter can draw on top or process the face data to accomplish its requirements.</p><p>I find it very convenient because the application using Warhol can forget about the cumbersome process of dealing with Vision and AVFoundation frameworks of Apple, focusing of what really makes an application different.</p><p>With the same goal in mind, to make the developer’s life easier, I proposed then that we can go one step forward in this path and include in the library one of the most common usage of Face Detection, to draw (silly) images on top of each feature. How cool would it be if the client could just pass an image for each feature and forget about drawing on top and the coordinates! That way they could compose a face overlay with a minimum of hassle.</p><p>With that ambition I started the ball rolling.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Td7AXP1Y2T_KV_-g8qXJnA.png" /></figure><h3>The Process</h3><p>To draw the images we will follow the same approach we implemented when first developing Warhol: The drawing, in this case the image drawing, is performed in a transparent view that is added on top of the camera. The Face Detection engine updates the View Model containing the Face Data and asks the data to draw with setNeedsDisplay Then draw(_ rect: CGRect) is called in our view where the drawing magic happens.</p><p>As I pointed earlier, the client should only be required to provide an Image for each Face Landmark. They can forget about coordinates or other extra information and focus on the design looks.</p><p>It is therefore Warhol’s task to deal with the coordinates, so we can can draw the provided image on the right place. Given that we obtain the landmark area as an array of points, we should first convert it into the rect where the image will be draw:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/885de6539512688465a9daa3848694e9/href">https://medium.com/media/885de6539512688465a9daa3848694e9/href</a></iframe><p>Once we have the target rectangle, we can add the image with layout.image.draw(in: rect). The outcome is:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/375/1*nwf4ThjqY5voyyAWIX0oMw.jpeg" /></figure><p>Oh it looks ok, but that is not probably what the client wants. Given that the provided eyes area are actually kinda small, we should arrange a way to resize it, so it can be bigger (or smaller) according to the app input. The latter should be also customizable in relation to each Landmark, some items can be bigger while others not. To tackle that, I created a SizeRatio struct with which the developer can express how big the image should be in relation with the original feature area:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3527a3c3e2d449ed8c1a3d50388a3a85/href">https://medium.com/media/3527a3c3e2d449ed8c1a3d50388a3a85/href</a></iframe><p>Notice how we can specify a different width and height ratio. This is especially relevant for the eyes case, where the width should be the same as the original but the height much bigger.</p><p>Once we have the SizeRatio, we resize the rect increasing the area but keeping the center point the same as the original:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/df02136b1e16dabafc2eb984103317b8/href">https://medium.com/media/df02136b1e16dabafc2eb984103317b8/href</a></iframe><p>Now it looks much better, we made the eyes bigger but the nose the same size:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/375/1*XSxMZfY_TPXvLULo2ZskLQ.jpeg" /></figure><p>Yeah! That’s acceptable. We found the perfect size for the eyes. The nose did not need any processing.</p><h3>Real time updates</h3><p>At this point the outcome was good, but there was one further concern. Since for simplicity sake I was using UIKit to draw the image instead of CoreGraphics, the image refresh might be slow when the features area change, as when the eyes blink or the mouth opens. UIKit is built on top of CoreGraphics, that is a more low level Framework, consequently providing more flexibility at the cost of more complexity. For instance, with CoreGraphics with can draw in a background thread because it is thread safe, which is not possible with UIKit. Happily, UIKit proved itself to be quite reliable for this case:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F414526818%3Fapp_id%3D122963&amp;dntp=1&amp;display_name=Vimeo&amp;url=https%3A%2F%2Fvimeo.com%2F414526818&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F887631853_295x166.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=vimeo" width="320" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c4f7e9875dfbfe1711a81c6bbc62ce1/href">https://medium.com/media/2c4f7e9875dfbfe1711a81c6bbc62ce1/href</a></iframe><p>That is nice! The layout updates at real time without any perceptible delay.</p><h3>Features Offset</h3><p>We are almost done, but there is one more functionality widely used in Instagram Filters that I could add to my project:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/628/1*_08xX062ZSKsLBU35MuP7Q.png" /><figcaption>Filter images are added under the eyes</figcaption></figure><p>In this case, the filter images for the eyes are not placed exactly on top, but a little bit below. To handle this case, I added an offset property in the ImageLayout struct. Using it, we can draw them where we wish:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/de3053e4732ef320eae5e03575deb6bc/href">https://medium.com/media/de3053e4732ef320eae5e03575deb6bc/href</a></iframe><h3>Wrapping it up</h3><p>So this is it! In this story we have seen how you can use Warhol now to:</p><ul><li>Create a Face overlay by adding filter images just by specifying the face feature where they should be placed, without having to deal with their coordinates.</li><li>Change the size of each of them at wish to create more visual effects.</li><li>Ensure that the Overlay is refreshed in the camera accordingly on real time, without any visible delays or poor performance.</li><li>Place the image layouts with an offset in relation with the Face Feature, to add more flexibility to your filters.</li></ul><p>As I mentioned in the previous story, there is plenty of room for improvements and new features in the field of Face Detection. In the next future I will be focusing on ARKit to animate facial expressions in real-time. Only devices with TrueDepth Camera (iPhone X onwards) will support it, so for the rest of them we will keep using the Vision Framework as described here.</p><p>As always, comments and proposals are more than welcome, just drop me a comment or message here. And of course, I would love you for the contribution to Warhol. PRs are appreciated with new ideas, improvements, fixes, and suggestions. This project is under MIT license and in case of issues please use the dedicated section in GitHub.</p><p>Happy Overlay!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ae5b8d40924d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/warhol-ii-compose-your-overlay-on-top-of-the-detected-face-hassle-free-for-ios-ae5b8d40924d">Warhol II: Compose your Overlay on Top of the Detected Face Hassle-Free for iOS</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>