<?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 Mat Schmid on Medium]]></title>
        <description><![CDATA[Stories by Mat Schmid on Medium]]></description>
        <link>https://medium.com/@matschmidy?source=rss-27567a789d3d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*00nveoZKtERDhvUopNOfRQ.jpeg</url>
            <title>Stories by Mat Schmid on Medium</title>
            <link>https://medium.com/@matschmidy?source=rss-27567a789d3d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 08 Apr 2026 01:04:32 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@matschmidy/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[SwiftUI Basics: List Fetching]]></title>
            <link>https://medium.com/@matschmidy/swiftui-basics-list-fetching-9b03fb145d85?source=rss-27567a789d3d------2</link>
            <guid isPermaLink="false">https://medium.com/p/9b03fb145d85</guid>
            <category><![CDATA[combine]]></category>
            <category><![CDATA[rest-api]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[objectbinding]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Mat Schmid]]></dc:creator>
            <pubDate>Wed, 12 Jun 2019 15:42:38 GMT</pubDate>
            <atom:updated>2019-06-12T15:42:38.042Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/718/1*_d9LiHJGn8N-31b4IPNbYg.png" /></figure><p><em>Disclaimer: This was written within the first week of SwiftUI being released. Some of this content might be outdated at the time of reading.</em></p><p>📦 Source code for this project is linked at the bottom of the article.</p><p>With SwiftUI being just released, everyone has been really excited and focused on (re)building their nice UI using it. However, not many have dug deep into building and handling the lifecycle of “real world” app — which primarily consists of fetching data and displaying it in a list.</p><p>This article will dive into the basics of maintaining state throughout the “real world” app lifecycle. This will include:</p><ul><li>Using BindableObject + URLSession to request and decode JSON payloads into Identifiable models.</li><li>Gracefully handling loading and and error states using a generic LoadableState enum.</li><li>Conditionally displaying View elements based on state.</li><li>Fetching and displaying images from a URL.</li><li>Adding UIActivityIndicator as an unofficial View element.</li></ul><h3>The demo app</h3><p>For the purposes of this article, I will be building and app which catalogues a store’s products. The JSON API used is in the following format:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/056322bab86dbb74122567e149a700ec/href">https://medium.com/media/056322bab86dbb74122567e149a700ec/href</a></iframe><p>The UI of the app itself will be simple — displaying the image, title, and body of each product in a row.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SSTZxVetaqf3KO46mSefBQ.png" /><figcaption>SwiftUI supports light and dark mode with no added work</figcaption></figure><h3>Models</h3><p>With the API laid out above, we can represent our data using the following models:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/30a70c12e2a5a9efcc47dded1ed0ac0a/href">https://medium.com/media/30a70c12e2a5a9efcc47dded1ed0ac0a/href</a></iframe><p>It’s important to note that any model which contains UI data must conform to Identifiable. These will also need to conform to Decodable as they will be constructed using JSONDecoder when parsing the network responses — hence the property names and types matching those in the API.</p><h3>Stateful list rendering</h3><p>The basis of our stateful list rendering will revolve around this generic LoadableState&lt;T&gt; enum. The fetched case has an associated value of a <a href="https://developer.apple.com/documentation/swift/result">Result</a> type— this will contain either a success or a failure response.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/737af8ffc70c4f50554c24f8b7f3b1a6/href">https://medium.com/media/737af8ffc70c4f50554c24f8b7f3b1a6/href</a></iframe><p>This state represents three cases:</p><ul><li>.loading: Awaiting a network response.</li><li>.fetched(.failure(FetchError)): The network response contained an error, where FetchError represents a description of the error.</li><li>.fetched(.success(T)): The network response returned successfully with a payload, where T represent the model type.</li></ul><h4>Usage in a View Builder</h4><p>From this state, we can display the relevant content to the user. Ideally, we would switch over this enum in the body of our View and return different View elements accordingly — but, at least in the current SwiftUI beta, this is not possible. Xcode will show you compile errors such as,</p><blockquote>Closure containing control flow statement cannot be used with function builder ‘ViewBuilder’</blockquote><p>when conditionally displaying view elements, or,</p><blockquote>Function declares an opaque return type, but the return statements in its body do not have matching underlying types</blockquote><p>when different View types are returned conditionally.</p><p>To get around this issue, SwiftUI provides a wrapper on any View object to be used such that there is only one underlying type being returned — appropriately named AnyView.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cf4e5b30099163a21c273772bf676f2d/href">https://medium.com/media/cf4e5b30099163a21c273772bf676f2d/href</a></iframe><p>With this AnyView wrapper, our body can be kept slim and the logic can be extracted into this stateContent computed property. While loading, we’ll show a spinner in the view (👀 have a look at the bottom of this article for implementation details). If the response contains an error, we’ll show the error description as plain Text, otherwise we’ll show the list of products. We can wrap this all in a NavigationView named “Products” in the body for a finished look.</p><h3>Fetching data</h3><p>SwiftUI introduces many new tools — one of those,BindableObject, serves data between a model and a view. In this BindableObject class, we will perform a URLSession network request and parse the results into a LoadableState. If no errors occur, JSONDecoder is used to parse the data into its respective models. The state, initialized as .loading, will use PassThroughSubject (available through BindableObject) to send an update to its listeners whenever it is changed. Views become listeners for these updates using the @ObjectBinding property delegate, as seen above in the ProductListView.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d0db04c6593fcde28b6bf071e627181c/href">https://medium.com/media/d0db04c6593fcde28b6bf071e627181c/href</a></iframe><h3>Rendering images from a URL</h3><p>As the JSON API used returns image URLs, we’ll need to convert those to UIImages. A similar approach used for product fetching can be used here, however, rather than sending updates in the form of a state, we will send Data.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/717cad191a1a8ba3d17f5d37eb54ece9/href">https://medium.com/media/717cad191a1a8ba3d17f5d37eb54ece9/href</a></iframe><p>Using this data, we can construct LoadableImageView — a stateful image View. A spinner will be show in this view while awaiting image data.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d8ca64d71141d8dbc6060de33e51c5fd/href">https://medium.com/media/d8ca64d71141d8dbc6060de33e51c5fd/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/414/1*4zJpgYuRrxBCnIX7RE3PSw.gif" /><figcaption>A spinner is used as the placeholder while an image loads</figcaption></figure><p>That’s all! With this, we’ve built a stateful list that fetches data and images from an external source. 🎉</p><h4><strong>Bonus</strong>: ActivityIndicator View</h4><p>SwiftUI comes with a lot of out-of-the-box View elements, but have yet to port a select few. Luckily, the UIViewRepresentable protocol enables us to build out the missing ones. Use this snippet to show a spinner on any View:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0de64ed20ef3af64da5377954ae4d0bf/href">https://medium.com/media/0de64ed20ef3af64da5377954ae4d0bf/href</a></iframe><p><strong>📦 Source code:</strong></p><p><a href="https://github.com/schmidyy/SwiftUI-ListFetching">schmidyy/SwiftUI-ListFetching</a></p><p>Thanks for reading! Feel free to follow me on <a href="https://twitter.com/devschmidy">Twitter</a> and <a href="https://github.com/schmidyy">Github</a> for more like this 👨🏻‍💻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9b03fb145d85" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a Realtime iOS App Using Functional Table Data]]></title>
            <link>https://medium.com/shopify-mobile/building-a-realtime-ios-app-using-functional-table-data-87691c1922ac?source=rss-27567a789d3d------2</link>
            <guid isPermaLink="false">https://medium.com/p/87691c1922ac</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[uitableview]]></category>
            <category><![CDATA[realtime]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[firebase]]></category>
            <dc:creator><![CDATA[Mat Schmid]]></dc:creator>
            <pubDate>Wed, 17 Apr 2019 19:22:19 GMT</pubDate>
            <atom:updated>2019-06-28T17:47:46.326Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Omkp3BsT-qZhrjumCOGbBQ.png" /></figure><p>Stale data sucks. With the help of Firebase’s data subscription model, all the data shown in your app can be up to date and consistent across. This article will go over how we built a realtime contacts app using Firebase and FunctionalTableData (FTD) — a functional approach to maintaining view states.</p><p>Realtime Functional Table Data is a basic Contacts app built with Shopify’s <a href="https://github.com/Shopify/FunctionalTableData">Functional Table Data</a> and <a href="https://firebase.google.com/">Firebase</a>. The idea is simple; each screen subscribes to a model in Firebase and is notified with realtime snapshots every time it’s updated. Each snapshot is decoded client-side and passed to Functional Table Data which compares it to the previous state to insert, update, and remove sections and cells that have changed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*NCq_obVORpfR59Ps45qOLw.png" /></figure><p>Check out the Github project here: <a href="https://github.com/Campbell-Scott/RealtimeFunctionalTableData">https://github.com/Campbell-Scott/RealtimeFunctionalTableData</a></p><h3>Getting started</h3><p>Detailed instructions on how to get Realtime Functional Table Data up and running, along with configuring Firebase are available in the <a href="https://github.com/Campbell-Scott/RealtimeFunctionalTableData#installation-guide">README</a>.</p><p>With this, run the RealtimeFunctionalTableData target on any device!</p><h3>Project Structure</h3><p>As you might notice, this project isn’t built using the traditional Model-View-Controller design pattern. Functional Table Data helps separate view-level logic and concerns from the view controller. FTD facilitates this React-like view building with its efficient state diff’ing algorithms and its functional approach to maintaining view states. Here are the four component’s responsibilities in each view:</p><ol><li>the <em>state</em>: responsible for maintaining the current source of truth of the view’s data.</li><li>the <em>builder</em>: responsible for deciding which data from the state to display, in what style, and how to handle action events.</li><li>the <em>view controller</em>: responsible for performing or delegating actions passed from the builder, then updating the state accordingly.</li><li>the <em>service</em>: responsible for performing asynchronous tasks (such as network requests) and reporting the results.</li></ol><p>There are three views in this demo contacts app; List, Add, and Details. As you’ll see nested under Sections in the project, each of these have a respective View Controller and Builder. Since the state of these are so small, they currently live in the Builder files, but it wouldn’t hurt to extract them.</p><p>Let’s examine how the List view is built and organized! As previously explained, you’ll notice the View Controller (VC) doesn’t know anything about the User or the view elements. The VC keeps reference to a FunctionalTableData object which will be managing our table view and diff’ing when needed. The state for this view is an enum with two cases; .loading and .finished(result:). As the content shown on this list needs to be fetched via a network request, we initialize the state as loading, then update the state to finished when the up-to-date User object is received.</p><p>Whenever the state is updated, the render(state:) method is called with it. This method invokes the List Builder for TableSection objects, then uses FunctionalTableData’s renderAndDiff(sections:) to update the view with the new, up-to-date, data.</p><p>When the builder receives a new state, it decides what the list view should display based on its enum value. If the state is set to .loading, the builder will return a spinner cell. If the state is set to .finished(result:), the builder will return an array of ListCells, each representing a contact. Every cell is represented as a CellConfigType object, which holds its view, state and actions.</p><p>Cell actions (such as selection, or a textfield value changing) in FTD are protocol-based. Typically, a protocol with the Actionable nomenclature will be defined with a function representing each action to be used in that builder. Respective VCs simply conform to these protocols and define the behaviour for each action. In the case of the list view, one action is defined for the selection of a contact cell which pushes the Details VC of that contact.</p><p>Services are responsible for performing asynchronous/non-deterministic tasks (such as network requests) and reporting the results to a concrete instance of the ServiceDelegate. Services are vended to their consumers through the ServiceProvider. Since consumers communicate with every Service through a shared interface, each service can hide its own implementation details. This allows a developer to swap in any new Service implementation. For example, the FirebaseService in RealtimeFunctionalTableData implements subscribeToUser() by subscribing to a User document in Firestore and calling its delegate every time it receives an updated snapshot. Another Service might implement this by fetching a User from CoreData or a Realm Database, etc.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/984/1*4M0R8H-WCEHHA8VjsKTVsg.gif" /><figcaption>An event triggered on one client is immediately propagated to all other clients</figcaption></figure><p>With all this, our app never needs to worry about stale data being shown! All in all, this app features:</p><ul><li>Realtime syncing and rendering — no pull-to-refresh!</li><li>A functional approach to maintaining view states</li><li>Programmatic view layout — no more interface builder!</li><li>An agnostic network layer which accepts any service</li></ul><p>Come help us build Functional Table Data!</p><p><a href="https://www.shopify.com/careers">Careers and Jobs at Shopify</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=87691c1922ac" width="1" height="1" alt=""><hr><p><a href="https://medium.com/shopify-mobile/building-a-realtime-ios-app-using-functional-table-data-87691c1922ac">Building a Realtime iOS App Using Functional Table Data</a> was originally published in <a href="https://medium.com/shopify-mobile">Shopify Mobile</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What it’s like being an iOS Intern at Shopify]]></title>
            <link>https://medium.com/@matschmidy/what-its-like-being-an-ios-intern-at-shopify-97a48015212?source=rss-27567a789d3d------2</link>
            <guid isPermaLink="false">https://medium.com/p/97a48015212</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[interview]]></category>
            <category><![CDATA[intern]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[shopify]]></category>
            <dc:creator><![CDATA[Mat Schmid]]></dc:creator>
            <pubDate>Mon, 24 Sep 2018 16:24:51 GMT</pubDate>
            <atom:updated>2018-09-27T15:42:45.085Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PNnVeq5dgo-EQAES62qecw.jpeg" /></figure><p>After spending the summer working at Shopify as an intern on the iOS team, I thought I’d share the hiring process, technical challenges, as well as what I learned during my time there. Overall, this summer has been an incredible experience where I got to meet amazing people, work on really cool projects and grow tremendously as an individual.</p><h4>The hiring process</h4><p><em>Background and disclaimer;</em> I had roughly a year of professional iOS experience before applying for the internship. The current process will likely have changed from the one I describe. All in all, it took roughly 3 months between applying and getting my offer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/430/1*rIc1KgPRaDRQPw1_xBImkw.gif" /><figcaption>App I built for the application challenge</figcaption></figure><p>As many already know, the hiring process at Shopify is fairly unique. This begins with the application, which took me nearly 5 hours to complete. It involves answering some short form questions, building my own Shopify store, and building a small iOS app following the provided criteria. The app was a simple product list view with data and images pulled from a REST API endpoint, and for bonus points, add product pages and search functionality. I enjoy doing these types of challenges because I can do them on my own time and in my own environment.</p><p>The next step was the infamous Life Story interview, which is essentially an hour long video chat with a recruiter to talk about your background and how you got into the field you’re applying for. This isn’t a technical interview, although, during mine, we discussed my past projects and the tools I used to build them. I believe anyone can pass this interview as long as they show enough <em>authenticity</em> and <em>passion</em> for what they do.</p><p>The final step for my internship hiring process was a 2-part technical interview. I’m fortunate enough to be living in Ottawa (where Shopify’s headquarters is located) which gave me the opportunity to go on-site for this portion, but typically this step is also done over a video chat. The first part was a project demo where I showed off an app I built on my own time to two senior engineers and went through the code and architecture choices I made. The second part was a technical question along the realm of system design and scaling.</p><p>A very long couple of weeks later I got the call with my offer 🚀</p><p>For a more in depth description of the intern hiring process, I strongly recommend having a look at one of my fellow interns <a href="https://medium.freecodecamp.org/how-i-got-an-internship-at-shopify-432cbe8da58a">article on the subject</a>.</p><p><a href="https://medium.freecodecamp.org/how-i-got-an-internship-at-shopify-432cbe8da58a">How I got an internship at Shopify</a></p><h4>Technical hurdles</h4><p>There’s a lot to be learned when starting on a new team — especially on one of such large scale. Fortunately, each individual contributor at Shopify is given a mentor — they are an incredible resources when joining a team as they will likely have a lot of context on the work you do and will be able to answer your questions. For me, one the biggest technical challenges I had when starting was adapting to building views fully programmatically. Previously, most of the views I’d built were done in Interface Builder (i.e. Storyboards &amp; XIBs), which, in hindsight, is only sustainable for small-scale apps (merge conflicts suck 🙅‍️).</p><p>Having said that, another big change in coding styles for me was no longer using traditional UITableView / UICollectionView for building views. Since almost the entire app is some sort of table view, it wouldn’t make sense to not use a more functional approach. That said, Shopify uses their open source <a href="https://github.com/Shopify/FunctionalTableData">FunctionalTableData</a> (FTD) framework for constructing views. FTD facilitates building views by allowing state-based view rendering (this brings react-like thinking to mobile!). This framework heavily revolves around the <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder design pattern</a> which, in this case, segregates each view into 3 components;</p><ol><li>the <em>state</em>: responsible for maintaining the current source of truth of the view’s data.</li><li>the <em>builder</em>: responsible for deciding what data from the state to display, in what style, and how to handle action events.</li><li>the <em>view controller</em>: responsible for performing or delegating actions passed from the builder, then updating the state accordingly.</li></ol><p>That likely doesn’t make a whole lot of sense right now, and trust me, it took me awhile to understand what was going on — but it works <em>so well</em> when properly executed. For example, let’s say you want a cell that has a label on the left, and a checkmark on the right which is displayed conditionally, all you would need to do is tell your builder to create an instance of your checkmark cell template and pass data from the state it needs — such as the label’s text, a boolean whether or not the checkmark should be displayed, and an action block to be execute when the cell is selected. You can also optionally provide a ton of customizations for the cell’s style to perfectly match the design requirements. This approach has completely changed the way I think about building views and was incredibly eye-opening to me when I finally understood how all these working components were pieced together.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zi6t1NwzPSfwnKjc29dkWA.jpeg" /><figcaption>Inside Shopify’s Toronto office</figcaption></figure><p>In addition, all of my past experience when building an iOS clients with a network layer was either through REST API, or some sort of database integration like Firebase. However, Shopify changed that by introducing me to <a href="https://graphql.org/">GraphQL</a> (GQL). GraphQL is a query language that allows clients (i.e. iOS, Android, Web) to request and mutate exactly the data it needs for a given component. This allows for extreme flexibility when building views across multiple clients, and is especially beneficial on mobile clients in terms of saving network bandwidth for the user. I won’t go into many details here, but there are many <a href="https://www.howtographql.com/">great resources available</a> to teach beginners about the gist of GQL. I spent a decent majority of my time this summer working on building GraphQL queries and mutations which was a new and challenging experience for me. In order to work with GQL, it requires knowledge of this new query language, such as understanding the syntax and its components — like fragments. Of course, with everything new, it takes time to learn, but really pays of to understand.</p><p>Another thing to expect when working as a developer is doing code reviews. Shopify has a really good culture for their CR process where their developers typically dedicate up to a quarter of their day for doing reviews. This was a fairly new process for me as reviewing code was never a top priority during my previous day-to-day schedule. In order for me to properly set aside this time, and get in the habit of reviewing pull requests (PRs), I started scheduling 30 to 60 minute blocks in my calendar purely dedicated to doing code reviews. This dedicated time spent reading and reviewing my teammates code helped me understand how they approach problems, and, in turn, helped me improve my own coding practises. At times, it felt like my PRs were never going to get merged because of seemingly never-ending nit-picky requests, but, in hindsight, all of those little details go a long way when maintaining such a large codebase. Fortunately, with this strong culture of code reviews comes high standards of code.</p><p>On a less technical side, since Shopify is such a large organization, a lot of soft skills are needed to work efficiently — such as communication. There were times where I would be working on a feature that would require certain fields to be available for me from the server that weren’t already available. This would normally be fine — just ping the team which “owns” the relevant fields and try and borrow one of their backend dev’s time to get those exposed on GraphQL. However, when working on new features, it wasn’t always obvious if there was a team that owned the data you were looking for. This caused what seemed like a never ending pursuit to find someone with the necessary context to get what you needed. Dealing with this can be frustrating, but definitely taught me a lot about working on projects which spanned multiple teams.</p><h4>TL;DR — Takeaways</h4><p>Often the biggest takeaways from a work term are concepts not taught in school — such as being an effective team member. What stuck with me the most was the idea of <em>writing code for others, not yourself</em>. A common misconception for programers (especially found in Junior developers) is that the code they write should be as dense as possible, and use all the new and fancy APIs to impress their coworkers. In fact, this coding practise has a negative impact on your team, and is not specific to iOS developers either. After all, the ultimate goal when on a team is to write code which will be easy for others to read (and maintain).</p><p>Thankfully, Shopify provides an amazing environment for growth and supporting employees throughout the learning curve. They host weekly developer talks, team show and tells, community developer events, company-wide summits with workshops and <em>so much more</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XszaPCU-3Xi_DKTuu40qBQ.jpeg" /><figcaption>Dev Summit Day 1 event, part of RnD Summit 2018</figcaption></figure><p>If you’re up for the challenge, consider interning at Shopify!</p><p><a href="https://www.shopify.com/careers/interns">Internships at Shopify - Paid Internship Program</a></p><p>If you have any questions about the process, or enjoyed the article, feel free to reach out to me on <a href="https://medium.com/@matschmidy">Medium</a>, <a href="https://twitter.com/devschmidy">Twitter</a>, or <a href="https://github.com/schmidyy">Github</a> ⭐</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=97a48015212" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Swift — Custom Navigation Bar Image for iOS 11 Large Titles ]]></title>
            <link>https://medium.com/@matschmidy/swift-custom-navigation-bar-image-for-ios-11-large-titles-8a176d9cbaed?source=rss-27567a789d3d------2</link>
            <guid isPermaLink="false">https://medium.com/p/8a176d9cbaed</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[custom]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[navigation-bar]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Mat Schmid]]></dc:creator>
            <pubDate>Mon, 18 Jun 2018 23:55:15 GMT</pubDate>
            <atom:updated>2018-06-18T23:55:15.520Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*WGcWerO8A5CNKOph33iPWw.png" /><figcaption>&lt;- Standard iOS 11 nav bar| Custom nav bar-&gt;</figcaption></figure><p>Standard iOS components can get boring… Luckily, with Swift, customization is available everywhere! This article will demonstrate how to use a custom image for your navigation bar, while still maintaining all the functionality provided in a Navigation Controller. 🚀</p><p><strong>TL;DR</strong>: Clear the default nav bar image provided by Navigation Controllers using a bit of code and position your image in it’s place by constraining it to the view’s top, leading, and trailing anchors (be sure to not constrain to the safe area).</p><h3>1. Creating the custom header image</h3><p>Chances are the custom navigation bar header you have in mind for you app will need to be created manually. There are many ways to go about doing this, but the simplest for my needs could be done using <a href="https://www.sketchapp.com/">Sketch</a>. Using the vector tool, I was able to create the design I had in mind within a couple minutes. The dimensions here don’t really matter because of the excellent export presets Sketch has by default (the iOS preset provides standard, @2x and @3x sizes Xcode asks you for).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*G5eWev5NxE1wJm0kvGQe_w.png" /></figure><h3>2. Clear the default Navigation Bar image</h3><p>Assuming you already have a view controller embedded in a Navigation Controller, the next step is to strip the nav bar from the default provided header image. This is fairly straight forward, and can be done in a couple lines of code. Here is the function I use to do so; and note — I put it a struct for reuse purposes, but this is optional.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/674e1bd50d262563be9aa505c36eabb6/href">https://medium.com/media/674e1bd50d262563be9aa505c36eabb6/href</a></iframe><p>And this is how the method is called from the view controller:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e0d244dc60d6352621786971816f5707/href">https://medium.com/media/e0d244dc60d6352621786971816f5707/href</a></iframe><p>The above code snipet should be called from either viewDidLoad() or viewWillAppear(_:) in order to ensure it is executed before the user sees the view. If you run the app now, you should be able to notice the missing nav bar image. 🔥</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/996/1*C1eSdb34DBu2ACJ80fAzoA.png" /></figure><h3>3. Insert the custom header image</h3><p>Now that the navigation bar is clear, we can provide our own image. For the purposes of this article, I will do this using interface builder. This is as simple as dragging a UIImageView onto your view controller, providing the proper image, and setting the constraints.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/738/1*0e5QlId4uqQAs_x669r2Uw.png" /></figure><p>In order to set the constraints so that the iPhone X doesn’t clip the image, we need to constrain the imageView&#39;s top anchor to view&#39;s top anchor (not the safe area). In my case, setting the constraints to 0left a small gap along the edges, so a value of -2 should fix that.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/558/1*kxis84rG1xK6u8ntdwoFtA.png" /></figure><p>Of course, the height constraint will change depending on the image used. and, since my image is dark, I also went ahead and set the large title text colour to white, and the status bar to .lightContent.</p><p>At this point, the custom header should work as intended 🎉</p><h3>4. Handling device sizing and orientation</h3><p>You might notice the header image looks fine on the iPhone X, but on any other device it looks way too big. This is because there is a gap between a view&#39;s top anchor and a view&#39;s top safe area anchor on the X. Luckily, can easily adjust the height of the image through an IBOutlet reference to the heigh constraint of the image view. Full device sizing can be found <a href="https://stackoverflow.com/a/46192822">here</a>. Place this code in the same area we clear the navigation bar default image:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a8f18514f6292fd32f6609aa82486d3b/href">https://medium.com/media/a8f18514f6292fd32f6609aa82486d3b/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2d46ff1fb74dd517144accb1afa70c7a/href">https://medium.com/media/2d46ff1fb74dd517144accb1afa70c7a/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/891/1*5b6oeAssWEqzPieOPcKyew.png" /></figure><p>You might also notice the height of the header image height is way too tall when rotating the device to landscape. This can be easily handled in the willTransform(to:with) method provided in the view controller.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7e8a6daa6c89ca1098720e0bc8cb69cc/href">https://medium.com/media/7e8a6daa6c89ca1098720e0bc8cb69cc/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/788/1*_caS5yd9b65fUjomS6wKug.gif" /></figure><p>I didn’t include it in my examples, but this will also work with added bar button items to the nav bar. That’s it! Your custom navigation bar image should now work as intended 👌</p><p>Feel free to follow me on <a href="https://twitter.com/devschmidy">Twitter</a> and <a href="https://github.com/schmidyy">Github</a> for more content like this 👨🏻‍💻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8a176d9cbaed" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Implement Custom and Dynamic Map Marker Info Windows for Google Maps iOS]]></title>
            <link>https://medium.com/@matschmidy/how-to-implement-custom-and-dynamic-map-marker-info-windows-for-google-maps-ios-e9d993ef46d4?source=rss-27567a789d3d------2</link>
            <guid isPermaLink="false">https://medium.com/p/e9d993ef46d4</guid>
            <category><![CDATA[firebase]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[google-maps]]></category>
            <dc:creator><![CDATA[Mat Schmid]]></dc:creator>
            <pubDate>Sat, 02 Dec 2017 06:04:43 GMT</pubDate>
            <atom:updated>2019-02-20T14:37:43.442Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5iVNErXjg40epY1VGCO9ow.png" /><figcaption>image source: <a href="https://codyhouse.co/gem/custom-google-map/">https://codyhouse.co/gem/custom-google-map/</a></figcaption></figure><p><em>⚠️ This article is now over a year old and such some code might be outdated.</em></p><p>If you plan on implementing a map view in your iOS app, chances are you’re leaning towards using Google Maps, as opposed to Apple Maps — and I don’t blame you. Mapping apps have two common uses: providing directions, and indicating specific locations throughout the map. If your app will include the latter, map markers are the go-to tool to facilitate it. Info Windows are the views presented when a user taps on a marker — and because this is Swift, there’s a lot of potential functionality and information that can be presented in these views. While <a href="https://developers.google.com/maps/documentation/ios-sdk/start">the SDK guide provided by Google</a> does go into great detail on every individual map component supported, they don’t make it obvious as to how to piece it all together. Now, as I learned while working on my first map-centered app, not only are there no obvious tutorials or guides provided by Google themselves, there also aren’t any complete and polished guides available anywhere online.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O0HgMbsYT3q2wsfjj8ywWg.png" /></figure><h3>Assumptions</h3><p>Google Maps should be implemented and working in your app already. If you need help implementing Google Maps itself, there are plenty of easy to follow guides available throughout the web, and by Google themselves here: <a href="https://developers.google.com/maps/documentation/ios-sdk/start">https://developers.google.com/maps/documentation/ios-sdk/start</a></p><p>If you plan on implementing dynamic info windows, your App should also be backed by a database — in my case, I’ll be using Firebase. The database entries will store the coordinates of all your markers, as well as some data related to it.</p><p>In this guide, I’ll be going through creating a custom XIB file for your markers, displaying marker data in its UILabels, and handling button press events done on the marker. This will be done using Swift 3.</p><h3>1. Creating the Custom Marker View</h3><p>The first step is creating a new view file, which I named MapMarkerWindowView.xib. The XIB file view should be resized to your preferred info window size, and should hold all of your desired UI elements, such as UILabels, UIButtons, UISwitches, and anything else you might want to include. Don’t forget to lock all these elements into place using constraints. In this example, I have three labels, and one button.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/806/1*-bsOXn7QiNfKAXoJVxkFYA.png" /></figure><h3>2. Making the Associated Class File</h3><p>Next, create a new Swift file that will contain the class to control your view file, mine is named MapMarkerWindow.swift. This class should extend UIView, and have IBOutlet references to your UI elements. If you include elements in your view which require event handlers, such as UIButtons, reference these in your class with IBActions. In order to let your MapViewController class know these events have been triggered, you’ll need to create a delegate protocol along with event handling methods in your MapMarkerWindow.swift, and implement it in your MapViewController class. Additionally, create a public class method to instantiate the XIB file you’ve previously created. This will be required later when assigning the custom info window to the markers.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0804e5218ebe38a4c25355a4e30d56a8/href">https://medium.com/media/0804e5218ebe38a4c25355a4e30d56a8/href</a></iframe><h3>3. Loading the Marker Data from your Database</h3><p>Moving to the class that manages your Google Maps view, you’ll need to gather a dictionary of data relating to each marker you want to place on your map — this must include coordinates for the marker location. As previously mentioned, I’m storing my marker data on Firebase. Retrieve your marker data whichever way you need to, and make sure the latitude and longitude values are readily available. In my case, I will load all the data for each individual marker and store in a dictionary I call spot. Once you have the data, you’re ready to create the map marker — we’ll do this on a the main thread to offload the computations from the UI thread. At this point, you can use an image as a custom marker image and color it as you desire. Assign the position property of the marker to the coordinate values you previously loaded, and don’t forget to assign the userData property of the marker to the spot dictionary containing all the marker data. This step is important as any data you want to display on the info window will need to part of this userData dictionary associated to the marker. You should call this method from viewDidLoad.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/539047aaa618d6a4e241e3bb4614f33e/href">https://medium.com/media/539047aaa618d6a4e241e3bb4614f33e/href</a></iframe><h3>4. Implement the GMSMapViewDelegate methods</h3><p>Have your MapViewController extends from the GMSMapViewDelegate protocol. This will require you to implement a few methods, but first create two class properties:</p><pre>private var infoWindow = MapMarkerWindow()</pre><pre>fileprivate var locationMarker : GMSMarker? = GMSMarker()</pre><p>Next, create a function to return an instance of the custom view class you created</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4046ea946c480b60802b9d052f065dd6/href">https://medium.com/media/4046ea946c480b60802b9d052f065dd6/href</a></iframe><p>In viewDidLoad, be sure to assign self.infoWindow = loadNiB().</p><p>Now, we’ll implement some GMSMapViewDelegate methods. The primary method, which will allow you to get all your map data displayed on the info window, is the didTap marker method. Using the marker parameter passed in, we can access all of that markers data through marker.userData. Set your self.locationMarker class property to be this marker — this is so that we can later handle moving the info window appropriately if the map gets moved. We also want to reset the self.infoWindow class property to be loadNiB() again. At this point we can do any UI element configuration to the info window, such as adding a corner radius, or lowering the opacity. We also set the text of our info window’s label(s) here using the data provided in marker.userData. We also want to place the center point of the info window’s view to equal the center point of the marker here. A negative Y value offset will be required to place the info window above the marker.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dbcdd4b0d253e829354ccc52d8204143/href">https://medium.com/media/dbcdd4b0d253e829354ccc52d8204143/href</a></iframe><p>The other two delegate methods from the GMSMapViewDelegate protocol we will implement are didChange position and didTapAt coordinate. If the map view was moved while an info window is open, we want the info window to properly reposition itself to stay on top of the marker it was sourced from. Additionally, if a user taps elsewhere on the map, we will dismiss the info window from being presented.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/040fd5f9ac325a9e9a36ff60139cd8ed/href">https://medium.com/media/040fd5f9ac325a9e9a36ff60139cd8ed/href</a></iframe><p>At this point, if we run our app, the info window should be presented with its appropriate data.</p><h3>5. Handle event triggers from the info window</h3><p>If we want to execute a bit of code from the MapViewController when a button on the info window is tapped, we simply implement the MapMarkerDelegate protocol in that class. This will force us to call the didTapInfoWindow method we defined in that protocol. From here, we have full access to that markers data. This can be useful if we want to push a new view controller that requires the spots information.</p><p>That’s it! This should piece together all the working parts required to get a custom info window for your maps markers.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e9d993ef46d4" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>