Cocoacasts https://cocoacasts.com If you're looking for a quick fix, then I don't have anything to offer you. If you want to become a better Swift developer, then have a seat and let me share with you what I know. en-us Fri, 22 Sep 2023 21:16:58 +0000 Fri, 22 Sep 2023 21:16:58 +0000 40 Exploring Xcode's Debugging Tools Xcode offers developers a mature development environment with a powerful debugger. Under the hood, Xcode's debugging tools take advantage of LLDB, the debugger of the LLVM project. It isn't necessary to have a deep understanding of LLDB or LLVM to make use of Xcode's debugging tools, but it certainly doesn't hurt to become familiar with LLDB or LLVM. Wed, 20 Sep 2023 06:30:00 +0000 https://cocoacasts.com/debugging-apps-with-xcode-15-exploring-xcode-debugging-tools https://cocoacasts.com/debugging-apps-with-xcode-15-exploring-xcode-debugging-tools Where to Start Everyone makes mistakes, and developers are no different. As a developer, you spend a significant portion of your time debugging the code you write. It is an inextricable aspect of software development. Some bugs are easy to find, while others can make you scratch your head. Fri, 15 Sep 2023 06:30:00 +0000 https://cocoacasts.com/debugging-apps-with-xcode-15-where-to-start https://cocoacasts.com/debugging-apps-with-xcode-15-where-to-start Migrating from ObservableObject to Observable I'd like to end this series by taking advantage of the recently introduced Observable macro. The changes we need to make are small and focused, but we also run into a few issues. Let's get started. Wed, 6 Sep 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-integrating-the-observable-macro https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-integrating-the-observable-macro The Challenges of Asynchronous Unit Tests In this episode, we finish the unit test we started in the previous episode. Even though the implementation of the addLocation(with:) method of the AddLocationViewModel class isn't overly complex, writing a unit test for it is quite the challenge. Let's continue where we left off. Wed, 16 Aug 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-the-challenges-of-asynchronous-unit-tests https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-the-challenges-of-asynchronous-unit-tests Writing Asynchronous Unit Tests In this episode, we continue where we left off in the previous episode, that is, writing unit tests for the AddLocationViewModel class. This episode is an important one because it illustrates the impact asynchronous code can have on the unit tests you write. Wed, 2 Aug 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-writing-asynchronous-unit-tests https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-writing-asynchronous-unit-tests Unit Testing a Complex View Model In the previous episode, we wrote unit tests for a simple view model, the AddLocationCellViewModel struct. In this episode, we take it up a notch and write unit tests for a complex view model. We take the AddLocationViewModel class as an example. Wed, 19 Jul 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-unit-testing-a-complex-view-model https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-unit-testing-a-complex-view-model Unit Testing a Simple View Model One of the key benefits of the Model-View-ViewModel pattern is improved testability. It isn't possible to write unit tests for the SwiftUI views we created, but we can unit test the view models that drive those views. The good news is that writing unit tests for a well-designed view model isn't difficult. Sun, 9 Jul 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-unit-testing-a-simple-view-model https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-unit-testing-a-simple-view-model How to Set Up In-App Purchases with RevenueCat Offering a subscription product in your application involves more than integrating with Apple's StoreKit framework. You need to set up subscription products in App Store Connect, keep track of the user's subscription status, and restrict access to the content or features that are exclusive to subscribers. Things get even more complicated if your application offers multiple tiers or is available on multiple platforms. Wed, 14 Jun 2023 06:30:00 +0000 https://cocoacasts.com/how-to-set-up-in-app-purchases-with-revenuecat https://cocoacasts.com/how-to-set-up-in-app-purchases-with-revenuecat Injecting Dependencies with Swinject We hit a roadblock in the previous episode. The CurrentConditionsViewModel struct needs access to a Store object, but it is tedious to pass a Store object from one view model to the next. In this episode, we use a dependency injection library, Swinject, to make this much less of a problem. Thu, 18 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-injecting-dependencies-with-swinject https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-injecting-dependencies-with-swinject Deleting Locations The last feature we need to add is the ability to delete locations. The changes we need to make are small, but there is a problem we need to address. Let's start by adding a button to the CurrentConditionsView. Tue, 16 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-deleting-locations https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-deleting-locations Defining the States of the Location View The LocationView is always in one of two states, fetching weather data or displaying weather data. It is the LocationView itself that implicitly defines these states and that is limiting. Not only is it limiting, we cannot write unit tests for the states of the LocationView. In this episode, I show you a solution that is testable and extensible. Thu, 11 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-defining-the-states-of-the-location-view https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-defining-the-states-of-the-location-view Refactoring the Location View Model The LocationView still displays stub data. That is something we change in this episode. The LocationViewModel struct is responsible for fetching the weather data the LocationView displays. It uses that weather data to create view models for the CurrentConditionsView and the ForecastView. Wed, 10 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-location-view-model https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-location-view-model Refactoring the Forecast View Model In this episode, we refactor the ForecastViewModel struct and the ForecastCellViewModel struct. The ForecastViewModel struct drives the ForecastView, the bottom section of the LocationView. Let's get to work. Tue, 9 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-forecast-view-model https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-forecast-view-model Refactoring the Current Conditions View Model In this episode, we refactor the CurrentConditionsViewModel struct. Remember that the CurrentConditionsViewModel struct drives the CurrentConditionsView, the top section of the LocationView. The changes we need to make are small. Mon, 8 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-current-conditions-view-model https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-current-conditions-view-model Setting Up A Proxy Server with Swift and Vapor In yesterday's episode, I wrote about protecting your application's secretes with a proxy server. In today's episode, I show you how to set up a proxy server with Swift and Vapor. Sun, 7 May 2023 06:30:00 +0000 https://cocoacasts.com/setting-up-a-proxy-server-with-swift-and-vapor https://cocoacasts.com/setting-up-a-proxy-server-with-swift-and-vapor Protecting Secrets with a Proxy Server Most of the services your application interacts with require authentication. Authentication through a secret, an API key or a client secret, is a commonly used method. Your application includes the secret in the request it sends to the service. That is only possible if your application has access to the secret at runtime. Sat, 6 May 2023 06:30:00 +0000 https://cocoacasts.com/protecting-secrets-with-a-proxy-server https://cocoacasts.com/protecting-secrets-with-a-proxy-server Avoiding Code Duplication In the previous episode, we used the MeasurementFormatter class to format the raw values the Clear Sky API returns. This is convenient and we use the MeasurementFormatter class several more times in the next few episodes. In this episode, we create an elegant API that wraps around the MeasurementFormatter API to avoid code duplication. Fri, 5 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-avoiding-code-duplication https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-avoiding-code-duplication Refactoring the Location Cell View Model With the WeatherService protocol in place, we can refactor the view models that need to provide their views with weather data. In this episode, we focus on the LocationCell by refactoring the LocationCellViewModel class. Thu, 4 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-location-cell-view-model https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-location-cell-view-model Injecting Base URL and API Key In the previous episode, we hard-coded the base URL and the API key of the Clear Sky API in the WeatherClient class. I'm not a fan of hard-coding configuration details. In this episode, we explore an alternative approach. Wed, 3 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-injecting-base-url-and-api-key https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-injecting-base-url-and-api-key Fetching Weather Data In this episode, we add the ability to fetch weather data from the Clear Sky API and decode a WeatherData object from the API response. We apply a pattern that should feel familiar by now. Tue, 2 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-fetching-weather-data https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-fetching-weather-data Defining the Weather Data Model It is time to focus on one of the core aspects of the weather application we are building, fetching and displaying weather data. Thunderstorm displays placeholder data for the time being. That is something we change in this and the next episodes. Mon, 1 May 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-defining-the-weather-data-model https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-defining-the-weather-data-model What to Gift Your Programmer Friend? Being a programmer myself, I know how challenging it can be to find the perfect gift for a fellow coder. Programmers are often quirky with peculiar interests. Finding a gift that speaks to their passions can be, well, challenging. The good news is that there are plenty of options to delight any coder, whether they are a seasoned professional or just starting out. Thu, 27 Apr 2023 06:30:00 +0000 https://cocoacasts.com/best-gifts-for-programmers-in-2023 https://cocoacasts.com/best-gifts-for-programmers-in-2023 Decoupling User Defaults The user's defaults database acts as the store of the weather application we are building. That is fine, but most objects shouldn't be aware of that implementation detail. The LocationsViewModel and AddLocationViewModel classes are tightly coupled to the UserDefaults class, but that isn't necessary. In this episode, we decouple the LocationsViewModel and AddLocationViewModel classes from the UserDefaults class. Wed, 26 Apr 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-decoupling-user-defaults https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-decoupling-user-defaults Updating Locations in User Defaults In this episode, we revisit the addLocation(with:) method of the AddLocationViewModel class. In that method, the view model stores the location the user selected in the user's defaults database. Tue, 25 Apr 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-updating-locations-in-user-defaults https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-updating-locations-in-user-defaults What Are the Benefits of the Final Keyword in Swift The final keyword in Swift is often ignored or overlooked. That isn't surprising as it isn't immediately obvious what the benefits are of annotating a class, method, or property with the final keyword. In this episode, you learn about the obvious and less obvious benefits of diligently marking a class, method, or property as final. Mon, 24 Apr 2023 06:30:00 +0000 https://cocoacasts.com/swift-fundamentals-what-are-the-benefits-of-the-final-keyword-in-swift https://cocoacasts.com/swift-fundamentals-what-are-the-benefits-of-the-final-keyword-in-swift Persisting Locations in User Defaults You may remember that the LocationsView displays a static list of locations. We need to change that if we want to put the AddLocationView to use. We keep it simple and store the list of locations in the user's defaults database. Let's get to work. Wed, 12 Apr 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-persisting-locations-in-user-defaults https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-persisting-locations-in-user-defaults 0 Dependencies from the Podfile and 0 Total Pods Installed Sat, 8 Apr 2023 06:30:00 +0000 https://cocoacasts.com/0-dependencies-from-the-podfile-and-0-total-pods-installed https://cocoacasts.com/0-dependencies-from-the-podfile-and-0-total-pods-installed A .gitignore for Swift Projects I have been using the same .gitignore file for ages, making small changes as my needs changed over the years. In this episode, I walk you through the .gitignore file I use for Swift and Vapor projects. Wed, 5 Apr 2023 06:30:00 +0000 https://cocoacasts.com/a-gitignore-for-swift-projects https://cocoacasts.com/a-gitignore-for-swift-projects Refactoring the Add Location View In the previous episode, we declared the State enum. It defines the possible states of the AddLocationView. In this episode, we integrate the State enum into the AddLocationView. Wed, 5 Apr 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-add-location-view https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-refactoring-the-add-location-view Optimizing the User Experience The user can add locations using the AddLocationView, but there is room for improvement. The user experience isn't optimal at the moment. The AddLocationView doesn't show a progress view when the application is forward geocoding the address the user entered and the user is faced with an empty view if no matches are found. That is something we address in this episode. Wed, 29 Mar 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-optimizing-the-user-experience https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-optimizing-the-user-experience Improving the Testability of the Geocoding Client In the previous episode, we made the Core Location framework a dependency of the project. That is fine, but we don't want a dependency to compromise the testability of the project. In this episode, we use a proven and familiar pattern to improve the testability of the GeocodingClient class. Fri, 24 Mar 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-improving-the-testability-of-the-geocoding-client https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-improving-the-testability-of-the-geocoding-client Integrating the Core Location Framework The GeocodingClient class returns stub data for the time being. In this episode, we integrate the Core Location framework and take advantage of the geocoding APIs it offers. We use the geocoding APIs to forward geocode the address the user enters in the TextField of the AddLocationView to a collection of `Location` objects. Fri, 17 Mar 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-integrating-the-core-location-framework https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-integrating-the-core-location-framework Integrating the Geocoding Service The AddLocationView displays stub data for the time being. We change that in this and the next episode by integrating the Core Location framework. Apple's Core Location framework defines an API for forward geocoding addresses. We use that API to convert an address to a collection of placemarks. The application converts the placemarks to Location objects the AddLocationView can display. Wed, 15 Mar 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-integrating-the-geocoding-service https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-integrating-the-geocoding-service Populating the Add Location View In the next few episodes, we populate the AddLocationView. We break this task up into several smaller steps. We first populate the AddLocationView with stub data. Later in this series, we replace the stub data with data provided by the Core Location framework. Mon, 13 Mar 2023 06:30:00 +0000 https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-populating-the-add-location-view https://cocoacasts.com/mastering-model-view-viewmodel-with-swiftui-populating-the-add-location-view Extending Code Coverage with the Adapter Pattern In the previous episode, we used the adapter pattern to make the integration of the project with the Google SDK testable. In this episode, we put the theory to the test. We write unit tests for the GoogleAnalyticsService class to validate the integration of the project with the Google SDK. Fri, 10 Mar 2023 06:30:00 +0000 https://cocoacasts.com/building-type-safe-apis-in-swift-extending-code-coverage-with-the-adapter-pattern https://cocoacasts.com/building-type-safe-apis-in-swift-extending-code-coverage-with-the-adapter-pattern Testing the Untestable In the previous episodes, we unit tested the analytics library we built. The integration with the Google SDK is an aspect of the implementation we haven't talked about in detail. We shouldn't unit test the Google SDK itself, but can we unit test the integration with the project? That is the question we focus on in this episode. Wed, 8 Mar 2023 06:30:00 +0000 https://cocoacasts.com/building-type-safe-apis-in-swift-testing-the-untestable https://cocoacasts.com/building-type-safe-apis-in-swift-testing-the-untestable Filling in the Gaps of the Test Suite In the previous episodes, we used code coverage to help us write unit tests for the analytics library we built. This worked fine, but code coverage isn't perfect. Code coverage inspects which lines of code are executed when the test suite is run. The result may be misleading or incorrect at times. In this episode, we take a look at an important shortcoming of code coverage. Mon, 6 Mar 2023 06:30:00 +0000 https://cocoacasts.com/building-type-safe-apis-in-swift-filling-in-the-gaps-of-the-test-suite https://cocoacasts.com/building-type-safe-apis-in-swift-filling-in-the-gaps-of-the-test-suite Looking Beyond Code Coverage In the previous episode, we wrote the first unit test for the analytics library we built. In this episode, we write a few more unit tests and take advantage of the compiler to find gaps in the test suite. Sun, 5 Mar 2023 06:30:00 +0000 https://cocoacasts.com/building-type-safe-apis-in-swift-looking-beyond-code-coverage https://cocoacasts.com/building-type-safe-apis-in-swift-looking-beyond-code-coverage Unit Testing the Analytics Library The analytics library we built in this series is easy to use thanks to its intuitive API. The call site is no longer littered with string literals and the API the analytics library exposes is type safe. We don't stop here, though. I promised you that the analytics library would be testable. Let's focus on that aspect in the next few episodes. Wed, 1 Mar 2023 06:30:00 +0000 https://cocoacasts.com/building-type-safe-apis-in-swift-unit-testing-the-analytics-library https://cocoacasts.com/building-type-safe-apis-in-swift-unit-testing-the-analytics-library Decoupling the Analytics Library The analytics library we are building is tightly coupled to the GoogleAnalyticsClient class. Tight coupling negatively impacts testability and it is often an indication that there is room for improvement. In this episode, we decouple the analytics library from the GoogleAnalyticsClient class by taking a protocol-oriented approach. Let me show you how that works. Wed, 8 Feb 2023 06:30:00 +0000 https://cocoacasts.com/building-type-safe-apis-in-swift-decoupling-the-analytics-library https://cocoacasts.com/building-type-safe-apis-in-swift-decoupling-the-analytics-library