{"id":9737,"date":"2025-04-15T17:45:00","date_gmt":"2025-04-15T14:45:00","guid":{"rendered":"https:\/\/handoli.com\/index.php\/2025\/04\/15\/using-swifts-defer-keyword-within-async-and-throwing-contexts\/"},"modified":"2025-04-15T17:45:00","modified_gmt":"2025-04-15T14:45:00","slug":"using-swifts-defer-keyword-within-async-and-throwing-contexts","status":"publish","type":"post","link":"https:\/\/handoli.com\/index.php\/2025\/04\/15\/using-swifts-defer-keyword-within-async-and-throwing-contexts\/","title":{"rendered":"Using Swift\u2019s defer keyword within async and throwing contexts"},"content":{"rendered":"<p>Swift\u2019s <code>defer<\/code> keyword allows us to delay the execution of a given block of code until the current scope is exited. While that might initially not seem <em>that<\/em> useful (after all, can\u2019t we simply write that code at the end of the scope instead?), it turns out that when writing modern Swift code, we\u2019re quite often dealing with multiple potential exit points within our functions and closures \u2014 especially when writing code that <code>throws<\/code>, or when utilizing <code>async\/await<\/code>.<\/p>\n<p>Let\u2019s take a look at the following <code>SearchService<\/code> type\u2019s <code>loadItems<\/code> method as an example. It uses a <code>Database<\/code> API that requires a connection to be opened before any operations can be performed, and that connection then needs to be properly closed and cleaned up before new database requests can be accepted:<\/p>\n<pre class=\"splash\"><code><span class=\"s-keyword\">actor<\/span> SearchService {\n    <span class=\"s-keyword\">private let<\/span> database: <span class=\"s-type\">Database<\/span>\n    ...\n\n    <span class=\"s-keyword\">func<\/span> loadItems(maching searchString: <span class=\"s-type\">String<\/span>) <span class=\"s-keyword\">throws<\/span> -&gt; [<span class=\"s-type\">Item<\/span>] {\n        <span class=\"s-keyword\">let<\/span> connection = database.<span class=\"s-call\">connect<\/span>()\n\n        <span class=\"s-keyword\">do<\/span> {\n            <span class=\"s-keyword\">let<\/span> items: [<span class=\"s-type\">Item<\/span>] = <span class=\"s-keyword\">try<\/span> connection.<span class=\"s-call\">runQuery<\/span>(.<span class=\"s-call\">entries<\/span>(\n                matching: searchString\n            ))\n\n            connection.<span class=\"s-call\">close<\/span>()\n            <span class=\"s-keyword\">return<\/span> items\n        } <span class=\"s-keyword\">catch<\/span> {\n            connection.<span class=\"s-call\">close<\/span>()\n            <span class=\"s-keyword\">throw<\/span> error\n        }\n    }\n}<\/code><\/pre>\n<blockquote>\n<p>Note how we need to explicitly specify the type for our <code>items<\/code> above, since the <code>runQuery<\/code> method is generic, as it can return an array of any kind of database-compatible entry type that we\u2019re looking to retrieve.<\/p>\n<\/blockquote>\n<p>Because our code has two separate branches (one for when our <code>runQuery<\/code> call succeeds, and one for when an error is thrown), we need to write separate calls to <code>connection.close<\/code> within each branch. That might initially not seem like a big deal, but just like most code duplication, it increases the chance that we\u2019ll end up making a mistake, which could result in a quite major bug in this instance (as missing a <code>close<\/code> call would leave the database unable to accept additional requests).<\/p>\n<p>One way to solve the above problem would be to ensure that our code only has a single branch of execution. In the case of the above <code>loadItems<\/code> method, that could be done by using the closure-based <code>Result<\/code> initializer included in the standard library, which converts a throwing closure into a result, which can then be unwrapped once we\u2019ve closed our database connection \u2014 like this:<\/p>\n<pre class=\"splash\"><code><span class=\"s-keyword\">actor<\/span> SearchService {\n    <span class=\"s-keyword\">private let<\/span> database: <span class=\"s-type\">Database<\/span>\n    ...\n\n    <span class=\"s-keyword\">func<\/span> loadItems(maching searchString: <span class=\"s-type\">String<\/span>) <span class=\"s-keyword\">throws<\/span> -&gt; [<span class=\"s-type\">Item<\/span>] {\n        <span class=\"s-keyword\">let<\/span> connection = database.<span class=\"s-call\">connect<\/span>()\n\n        <span class=\"s-keyword\">let<\/span> result = <span class=\"s-type\">Result<\/span>&lt;[<span class=\"s-type\">Item<\/span>], <span class=\"s-type\">Error<\/span>&gt; {\n            <span class=\"s-keyword\">try<\/span> connection.<span class=\"s-call\">runQuery<\/span>(.<span class=\"s-call\">entries<\/span>(matching: searchString))\n        }\n\n        connection.<span class=\"s-call\">close<\/span>()\n        <span class=\"s-keyword\">return<\/span> <span class=\"s-keyword\">try<\/span> result.<span class=\"s-call\">get<\/span>()\n    }\n}<\/code><\/pre>\n<p>While that\u2019s certainly an improvement \u2014 let\u2019s now take a look at how <code>defer<\/code> lets us solve the problem in an arguably much more elegant way, since it\u2019ll let us define the closing of our database connection right next to where the connection is opened:<\/p>\n<pre class=\"splash\"><code><span class=\"s-keyword\">actor<\/span> SearchService {\n    <span class=\"s-keyword\">private let<\/span> database: <span class=\"s-type\">Database<\/span>\n    ...\n\n    <span class=\"s-keyword\">func<\/span> loadItems(maching searchString: <span class=\"s-type\">String<\/span>) <span class=\"s-keyword\">throws<\/span> -&gt; [<span class=\"s-type\">Item<\/span>] {\n        <span class=\"s-keyword\">let<\/span> connection = database.<span class=\"s-call\">connect<\/span>()\n        <span class=\"s-keyword\">defer<\/span> { connection.<span class=\"s-call\">close<\/span>() }\n\n        <span class=\"s-keyword\">return try<\/span> connection.<span class=\"s-call\">runQuery<\/span>(.<span class=\"s-call\">entries<\/span>(matching: searchString))\n    }\n}<\/code><\/pre>\n<p>Nice! Not only are the calls to <code>connect<\/code> and <code>close<\/code> now right next to each other (which arguably makes it easier to reason about those two calls as a pair), but because we can now directly return the result of our <code>runQuery<\/code> call, we no longer have to manually specify any type information \u2014 the compiler can now automatically infer the return type of that call for us.<\/p>\n<p>Using <code>defer<\/code> does have somewhat of a downside, though, in that it sort of breaks the traditional control flow model that structured programming tends to follow \u2014 where instructions are always executed from top to bottom. Within our current <code>loadItems<\/code> implementation, for example, we now have three expressions:<\/p>\n<ul>\n<li>1. Open the connection<\/li>\n<li>2. Close the connection (deferred)<\/li>\n<li>3. Run our query<\/li>\n<\/ul>\n<p>But those expressions won\u2019t be executed in the order <code>1, 2, 3<\/code>, but rather in the order <code>1, 3, 2<\/code>, which might initially seem like a quite strange way of structuring our code. So, using <code>defer<\/code> might end up being somewhat of an <em>acquired taste<\/em>, and a tool that should probably not be over-used, but rather just used when there\u2019s some specific cleanup work that we want to ensure gets performed no matter how the current scope is exited.<\/p>\n<h2>Async contexts<\/h2>\n<p>The <code>defer<\/code> keyword is perhaps even more useful in the concurrent world of <code>async\/await<\/code>, since one of the benefits of that way of writing async code is that it lets us \u201cflatten\u201d code that previously required nesting in the shape of closures or separate operations.<\/p>\n<p>For example, within the following <code>ItemListService<\/code>, we once again have to work with separate code branches (and thus, nesting) in order to ensure that an <code>isLoading<\/code> bool is set back to <code>false<\/code> whenever a loading operation was completed:<\/p>\n<pre class=\"splash\"><code><span class=\"s-keyword\">actor<\/span> ItemListService {\n    <span class=\"s-keyword\">private let<\/span> networking: <span class=\"s-type\">NetworkingService<\/span>\n    <span class=\"s-keyword\">private var<\/span> isLoading = <span class=\"s-keyword\">false<\/span>\n    ...\n\n    <span class=\"s-keyword\">func<\/span> loadItems(after lastItem: <span class=\"s-type\">Item<\/span>) <span class=\"s-keyword\">async throws<\/span> -&gt; [<span class=\"s-type\">Item<\/span>] {\n        <span class=\"s-keyword\">guard<\/span> !isLoading <span class=\"s-keyword\">else<\/span> { <span class=\"s-keyword\">throw<\/span> <span class=\"s-type\">Error<\/span>.<span class=\"s-property\">alreadyLoading<\/span> }\n        isLoading = <span class=\"s-keyword\">true<\/span>\n\n        <span class=\"s-keyword\">do<\/span> {\n            <span class=\"s-keyword\">let<\/span> request = <span class=\"s-call\">requestForLoadingItems<\/span>(after: lastItem)\n            <span class=\"s-keyword\">let<\/span> response = <span class=\"s-keyword\">try await<\/span> networking.<span class=\"s-call\">performRequest<\/span>(request)\n            <span class=\"s-keyword\">let<\/span> items: [<span class=\"s-type\">Item<\/span>] = <span class=\"s-keyword\">try<\/span> response.<span class=\"s-call\">decoded<\/span>()\n            \n            isLoading = <span class=\"s-keyword\">false<\/span>\n            <span class=\"s-keyword\">return<\/span> items\n        } <span class=\"s-keyword\">catch<\/span> {\n            isLoading = <span class=\"s-keyword\">false<\/span>\n            <span class=\"s-keyword\">throw<\/span> error\n        }\n    }\n}<\/code><\/pre>\n<p>In this case, we can\u2019t rely on the <code>Result<\/code>-based approach we took earlier to flatten our code into a single branch, since there\u2019s no built-in way to convert an <code>async<\/code> closure into a <code>Result<\/code> (although that\u2019s something we <em>could<\/em> add, using a custom extension). So this is a type of situation where <code>defer<\/code> really comes in handy, as it lets us ensure that our <code>isLoading<\/code> state is always assigned back to <code>false<\/code> whenever an operation either succeeded or failed:<\/p>\n<pre class=\"splash\"><code><span class=\"s-keyword\">actor<\/span> ItemListService {\n    <span class=\"s-keyword\">private let<\/span> networking: <span class=\"s-type\">NetworkingService<\/span>\n    <span class=\"s-keyword\">private var<\/span> isLoading = <span class=\"s-keyword\">false<\/span>\n    ...\n\n    <span class=\"s-keyword\">func<\/span> loadItems(after lastItem: <span class=\"s-type\">Item<\/span>) <span class=\"s-keyword\">async throws<\/span> -&gt; [<span class=\"s-type\">Item<\/span>] {\n        <span class=\"s-keyword\">guard<\/span> !isLoading <span class=\"s-keyword\">else<\/span> { <span class=\"s-keyword\">throw<\/span> <span class=\"s-type\">LoadingError<\/span>.<span class=\"s-property\">alreadyLoading<\/span> }\n        isLoading = <span class=\"s-keyword\">true<\/span>\n        <span class=\"s-keyword\">defer<\/span> { isLoading = <span class=\"s-keyword\">false<\/span> }\n\n        <span class=\"s-keyword\">let<\/span> request = <span class=\"s-call\">requestForLoadingItems<\/span>(after: lastItem)\n        <span class=\"s-keyword\">let<\/span> response = <span class=\"s-keyword\">try await<\/span> networking.<span class=\"s-call\">performRequest<\/span>(request)\n        <span class=\"s-keyword\">return try<\/span> response.<span class=\"s-call\">decoded<\/span>()\n    }\n}<\/code><\/pre>\n<p>The above type of approach can also be really useful when working with nested async tasks as well. For example, let\u2019s say that we wanted to improve the above <code>loadItems<\/code> method so that it doesn\u2019t throw an error if called while a loading operation is already underway. To do that, we could keep track of a dictionary of loading tasks (keyed by the ID of the <code>lastItem<\/code> for each task), and then use <code>defer<\/code> to ensure that a task is always removed from that dictionary when it was completed \u2014 like this:<\/p>\n<pre class=\"splash\"><code><span class=\"s-keyword\">actor<\/span> ItemListService {\n    <span class=\"s-keyword\">private let<\/span> networking: <span class=\"s-type\">NetworkingService<\/span>\n    <span class=\"s-keyword\">private var<\/span> activeTasksForLastItemID = [<span class=\"s-type\">Item<\/span>.<span class=\"s-type\">ID<\/span>: <span class=\"s-type\">Task<\/span>&lt;[<span class=\"s-type\">Item<\/span>], <span class=\"s-type\">Error<\/span>&gt;]()\n    ...\n\n    <span class=\"s-keyword\">func<\/span> loadItems(after lastItem: <span class=\"s-type\">Item<\/span>) <span class=\"s-keyword\">async throws<\/span> -&gt; [<span class=\"s-type\">Item<\/span>] {\n        <span class=\"s-keyword\">if let<\/span> existingTask = activeTasksForLastItemID[lastItem.<span class=\"s-property\">id<\/span>] {\n            <span class=\"s-keyword\">return try await<\/span> existingTask.<span class=\"s-property\">value<\/span>\n        }\n\n        <span class=\"s-keyword\">let<\/span> task = <span class=\"s-type\">Task<\/span> {\n            <span class=\"s-keyword\">defer<\/span> { activeTasksForLastItemID[lastItem.<span class=\"s-property\">id<\/span>] = <span class=\"s-keyword\">nil<\/span> }\n\n            <span class=\"s-keyword\">let<\/span> request = <span class=\"s-call\">requestForLoadingItems<\/span>(after: lastItem)\n            <span class=\"s-keyword\">let<\/span> response = <span class=\"s-keyword\">try await<\/span> networking.<span class=\"s-call\">performRequest<\/span>(request)\n            <span class=\"s-keyword\">return try<\/span> response.<span class=\"s-call\">decoded<\/span>() <span class=\"s-keyword\">as<\/span> [<span class=\"s-type\">Item<\/span>]\n        }\n\n        activeTasksForLastItemID[lastItem.<span class=\"s-property\">id<\/span>] = task\n        <span class=\"s-keyword\">return try await<\/span> task.<span class=\"s-property\">value<\/span>\n    }\n}<\/code><\/pre>\n<p>In general, the above technique is a neat way of preventing duplicate async actor requests, since actors only protect against simultaneous calls while they\u2019re busy performing <em>synchronous<\/em> work. Once an actor has started an async task using <code>await<\/code>, it\u2019s free to accept new calls while that async task is being performed. By using a nested <code>Task<\/code> combined with the <code>defer<\/code> keyword, we can ensure that such duplicate requests are properly reused and discarded once finished, all in a predictable manner.<\/p>\n<h2>Conclusion<\/h2>\n<p>Swift\u2019s <code>defer<\/code> keyword might initially seem like a somewhat odd language tool, as it doesn\u2019t strictly follow the top-to-bottom control flow order that structured programming tend to use. But when it comes to cleanup operations, state management, and other tasks that we want to ensure are run no matter how a given scope is exited, it can be a really great tool \u2014 especially when utilizing Swift concurrency and the language\u2019s native error handling model.<\/p>\n<p>If you\u2019ve got questions, comments, or feedback, then feel free to reach out via either <a href=\"https:\/\/mastodon.social\/@johnsundell\">Mastodon<\/a> or <a href=\"https:\/\/bsky.app\/profile\/johnsundell.bsky.social\">Bluesky<\/a>.<\/p>\n<p>Thanks for reading!<\/p>","protected":false},"excerpt":{"rendered":"<p>Swift\u2019s defer keyword allows us to delay the execution of a given block of code until the current scope is exited. While that might initially not seem that useful (after all, can\u2019t we simply write that code at the end of the scope instead?), it turns out that when writing modern Swift code, we\u2019re quite [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rop_custom_images_group":[],"rop_custom_messages_group":[],"rop_publish_now":"initial","rop_publish_now_accounts":[],"rop_publish_now_history":[],"rop_publish_now_status":"pending","footnotes":""},"categories":[1,15],"tags":[],"class_list":["post-9737","post","type-post","status-publish","format-standard","hentry","category-explore","category-world"],"_links":{"self":[{"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/posts\/9737","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/comments?post=9737"}],"version-history":[{"count":0,"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/posts\/9737\/revisions"}],"wp:attachment":[{"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/media?parent=9737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/categories?post=9737"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/handoli.com\/index.php\/wp-json\/wp\/v2\/tags?post=9737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}