[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"site-settings":3,"blogpost-migrating-your-project-to-the-new-swift-concurrency-using-async-await":72},{"footer":4,"contact_form":6,"chat_widget":11,"accolades":19,"seo_social":63},{"iso_notice":5},"Wolfpack Digital is an ISO 9001:2015, ISO 27001:2013 and ISO 14001:2015 certified company - © _YEAR_ Wolfpack Digital. All rights reserved.",{"budgets":7},[8,9,10],"Under $50.000","Between $50.000 - 200.000","Over $200.000",{"consent":12},{"greeting":13,"title":14,"body":15,"accept_label":16,"decline_label":17,"declined_message":18},"Awoo! I'm Wolfpack Digital's AI assistant. Ask me anything about our services, process, or team, and if you want a project estimate, I can point you to our AI Estimator.","Data Privacy","\u003Cp>Hi there! We would love to talk with you. Under the EU General Data Protection Regulation, we need your approval for our use of personal information (e.g. your name and email address) you may provide as we communicate:\u003C\u002Fp>\n\u003Col>\n  \u003Cli>We'll store your personal information so that we can pick up the conversation if we talk later.\u003C\u002Fli>\n  \u003Cli>We may send you emails to follow up on our discussion here.\u003C\u002Fli>\n  \u003Cli>We may send you emails about our upcoming services and promotions.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Is this okay with you?\u003C\u002Fp>","Yes, I Accept","No, Not Now","No problem. Come back if you change your mind.",{"winnersOfList":20,"awardsList":29,"inHouseAppImages":46,"certificationsList":50},[21,25],{"alt":22,"href":23,"image":24},"European Awards","https:\u002F\u002Fwww.theeuropeanawards.eu\u002Fpremiado\u002Fwolfpack-digital-awarded-in-the-app-development-category","\u002Fimages\u002Fabout-us\u002Fwinners\u002Feuropean.svg",{"alt":26,"href":27,"image":28},"Webby Awards","https:\u002F\u002Fwinners.webbyawards.com\u002F2024\u002Fwebsites-and-mobile-sites\u002Fresponsible-technology\u002Fresponsible-ai\u002F275408\u002Fequality-ai-fair-and-unbiased-algorithms-to-eliminate-discrimination-in-machine-learning-models","\u002Fimages\u002Fabout-us\u002Fwinners\u002Fwebby.svg",[30,34,38,42],{"alt":31,"href":32,"image":33},"Clutch 1000 List Reveals Top-Rated Business Service Providers of 2023","https:\u002F\u002Fclutch.co\u002Fpress-releases\u002Fclutch-1000-fall-2023","\u002Fimages\u002Fabout-us\u002Fawards\u002Fclutch.svg",{"alt":35,"href":36,"image":37},"Clutch Recognizes the 1000 Best B2B Service Providers in its Exclusive 2019 Clutch 1000 List","https:\u002F\u002Fclutch.co\u002Fpress-releases\u002Frecognizes-1000-best-b2b-service-providers-its-exclusive-2019-1000-list","\u002Fimages\u002Fabout-us\u002Fawards\u002Fglobal.svg",{"alt":39,"href":40,"image":41},"Mobile App Daily Award","","\u002Fimages\u002Fabout-us\u002Fawards\u002Fmobile-app-daily.svg",{"alt":43,"href":44,"image":45},"Manifest Award","https:\u002F\u002Fthemanifest.com\u002Fro\u002Fweb-development\u002Fcompanies","\u002Fimages\u002Fabout-us\u002Fawards\u002Fmanifest.svg",[47],{"alt":48,"href":40,"image":49},"Wolfpack Labs","\u002Fimages\u002Fhomepage\u002Fawards\u002Flabs.svg",[51,55,59],{"alt":52,"href":53,"image":54},"ISO 27001 Certification","https:\u002F\u002Fwww.qscert.com\u002Fcs\u002Fissued-certificates\u002F?certID=_7690LD367","\u002Fimages\u002Fabout-us\u002Fcertifications\u002Fiso-27001.svg",{"alt":56,"href":57,"image":58},"ISO 9001 Certification","https:\u002F\u002Fwww.qscert.com\u002Fcs\u002Fissued-certificates\u002F?certID=_7690LBDB0","\u002Fimages\u002Fabout-us\u002Fcertifications\u002Fiso-9001.svg",{"alt":60,"href":61,"image":62},"ISO 14001 Certification","https:\u002F\u002Fwww.qscert.com\u002Fma\u002Fissued-certificates\u002F?certID=_7690LZSGS","\u002Fimages\u002Fabout-us\u002Fcertifications\u002Fiso-14001.svg",{"default_og_image_urls":64,"default_og_image_alt":68,"og_site_name":68,"og_locale":69,"twitter_site":70,"page_type_defaults":71},[65],{"style":66,"url":67},"og","\u002Fimages\u002Fsocial_share_preview.jpg","Wolfpack Digital","en_US","@DigitalWolfpack",{},["Reactive",73],{"title":74,"body":75,"slug":76,"featured_image_urls":77,"meta_tags":102,"reading_time":111,"title_size":112,"tag_list":113,"formatted_published_at":114,"short_description":104,"categories":115,"alt_text":110,"published_at":117,"content_updated_at":118,"formatted_content_updated_at":118,"key_takeaways":119,"faqs":125,"updated_at":138,"canonical_override":40,"no_index":139,"canonical_url":140,"publishers":141},"Migrating your project to the new Swift concurrency using async\u002Fawait","\u003Ch2>Async\u002Fawait in Swift concurrency\u003C\u002Fh2>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Async\u002Fawait is part of Swift's structured concurrency model, introduced in Swift 5.5 and now a mature, standard part of the language. Concurrency means letting multiple pieces of code run at the same time. With async functions and await statements, you can define asynchronous sequences in a clean, readable way.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Ch2>Why migrate your iOS project to async\u002Fawait?\u003C\u002Fh2>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>As an iOS developer, you might ask why you should adopt async\u002Fawait and update an existing project. Using it only on new projects is easier, true. But refactoring a current one gives you much cleaner, better-structured code.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Here are the benefits I found after migrating to async\u002Fawait:\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Col>\n\u003Cul>\u003Cli>Fewer completion handlers. Repeating @escaping (Result&lt;T, APIError&gt;) -&gt; Void gets frustrating. Async\u002Fawait removes nested handlers and makes code more readable.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>Cleaner error handling. Async\u002Fawait pairs beautifully with do-try-catch blocks.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>Less risk of hanging completions. You must return a value or throw an error, so you can't forget to call a completion.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>Synchronous-looking code. Asynchronous code reads like synchronous code, so it is easier to reason about.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>Less code overall. Files get shorter and clearer.\u003C\u002Fli>\u003C\u002Ful>\n\u003C\u002Fol>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Let's see how to migrate the most common iOS scenarios. We'll start with a traditional async project, move through the layers of a well-structured app, then handle multiple API calls and group them. Finally, since many projects use \u003Cstrong>Alamofire\u003C\u002Fstrong> on the networking side, we'll cover that too.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Ch2>Example project: a News app\u003C\u002Fh2>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Our example is a News app that fetches and displays articles from a REST API. The project has a view, a view model, a data model, and a simple networking layer.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Xcode Project Navigator showing the AsyncAwait sample project with Scenes, Models, and Network folders\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F766\u002Fcontent_image9.png\" style=\"width: 300px; height: 495px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Ch3>Components\u003C\u002Fh3>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Let's look at the networking components and the view model.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cstrong>1. APIService\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>This struct has a \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fwww.wolfpack-digital.com\u002Fblogposts\u002Fdifferences-between-static-websites-spa-and-ssr\" target=\"_blank\">static\u003C\u002Fa>\u003C\u002Fstrong> generic request method. It expects a route conforming to \u003Cstrong>APIProtocol\u003C\u002Fstrong> plus a completion handler. It runs a basic URL request with a data task, decodes the data, then passes the result or error to the completion handler.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Original APIService struct using a completion handler with a URLSession data task\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F767\u002Fcontent_image11.png\" style=\"width: 600px; height: 394px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cstrong>2. APIProtocol\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>This protocol is the interface for API routes. It defines a method, path, optional body parameters, and query items. Its \u003Cstrong>asURLRequest()\u003C\u002Fstrong> method builds a basic URLRequest.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"APIProtocol definition with an asURLRequest method that builds a URLRequest\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F768\u002Fcontent_image7.png\" style=\"width: 600px; height: 765px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cstrong>3. NewsAPI\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>This enum holds all news-related endpoints. For simplicity, we'll focus on the \u003Cstrong>getNews\u003C\u002Fstrong> case.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"NewsAPI enum defining the getNews endpoint method, path, and query items\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F769\u002Fcontent_image12.png\" style=\"width: 600px; height: 713px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cstrong>4. NewsViewModel\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>The view model holds a news array and fetches data through the APIService request method. In a larger project, a repository or data source layer would handle this.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"NewsViewModel calling APIService with a completion handler and a Result switch\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F770\u002Fcontent_image10.png\" style=\"width: 600px; height: 515px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Ch2>Migrating to async\u002Fawait\u003C\u002Fh2>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cstrong>1. Updating the APIService\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Refactored async throws APIService using URLSession async data and throwing errors\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F771\u002Fcontent_image1.png\" style=\"width: 600px; height: 422px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Here is what changed in this method:\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Col>\n\u003Cul>\u003Cli>The signature is now marked \u003Cstrong>async throws\u003C\u002Fstrong> and returns a \u003Cstrong>Decodable\u003C\u002Fstrong> type.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>Because the method is async, we use URLSession's \u003Cstrong>async data(for:)\u003C\u002Fstrong>. It returns a tuple with the Data object and the URLResponse.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>The decoded data is returned directly, with no completion handler.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>Error handling is simpler with \u003Cstrong>throw\u003C\u002Fstrong>. You either return a value or throw an error.\u003C\u002Fli>\u003C\u002Ful>\n\u003C\u002Fol>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Refactoring this file dropped the line count from 38 to 33, removing about \u003Cstrong>13%\u003C\u002Fstrong> of the code. That may seem small, but this is a very simple example. Real projects hold far more complex code.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cstrong>2. Updating the view model\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Now that the APIService is refactored, here is how the view model looks:\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Refactored NewsViewModel using a Task, do-catch, and MainActor.run to update the UI\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F772\u002Fcontent_image6.png\" style=\"width: 600px; height: 410px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>So what changed?\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Col>\u003Cul>\u003Cli>We create a \u003Cstrong>Task\u003C\u002Fstrong>, a unit of asynchronous work. Without it, we get this error:\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fol>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Xcode error: async call in a function that does not support concurrency\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F773\u002Fcontent_image5.png\" style=\"width: 600px; height: 83px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Col>\n\u003Cul>\u003Cli>We use a \u003Cstrong>do-try-catch\u003C\u002Fstrong> structure. Not everyone loves it, but it adds clarity and is common in many languages.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>We call the request method with \u003Cstrong>try await\u003C\u002Fstrong>. These keywords make clear that execution continues only once a response arrives.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>Because the awaited call runs on a background thread, we update the \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fwww.wolfpack-digital.com\u002Fblogposts\u002Fbuilding-your-apps-ui-for-2023-part-1\" target=\"_blank\">UI\u003C\u002Fa>\u003C\u002Fstrong> on the main thread. We use \u003Cstrong>await MainActor.run\u003C\u002Fstrong> to switch to the main thread before setting the published news array.\u003C\u002Fli>\u003C\u002Ful>\n\u003C\u002Fol>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>But what if you need \u003Cstrong>multiple API calls\u003C\u002Fstrong>? To show this, let's add a call that fetches a \"People of the Day\" section. The view model then looks like this:\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"NewsViewModel making two sequential await API calls inside one Task\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F774\u002Fcontent_image8.png\" style=\"width: 600px; height: 458px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Since the second call runs right after the first, a failure in the first one is caught and no data displays. To avoid that, use two separate methods, such as loadNews() and loadPeopleOfTheDay(). That way, if one fails and the other succeeds, the good data still displays and the error is handled.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Ch2>Grouped API calls\u003C\u002Fh2>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Async\u002Fawait also lets you group tasks and wait for all of them to finish before moving on.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>To show this, let's add a \u003Cstrong>getReadTime\u003C\u002Fstrong> call that fetches the reading time of each article in seconds. Assume we must make a separate call per article.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"NewsViewModel using withThrowingTaskGroup to run grouped read-time tasks concurrently\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F775\u002Fcontent_image3.png\" style=\"width: 600px; height: 501px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>To group tasks, we use \u003Cstrong>await withThrowingTaskGroup(of:)\u003C\u002Fstrong>. This one is a bit more complex, so let's see what the documentation says:\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Apple documentation for the withThrowingTaskGroup function\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F776\u002Fcontent_image2.png\" style=\"width: 600px; height: 590px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Looking at our code:\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Col>\n\u003Cul>\u003Cli>A group returns a result. Here the child tasks return nothing; they just update the news items. So the result is (), hence the _ = try await withThrowingTaskGroup(of: ...).\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>For each news item, we create a loadReadTime task and add it to the group.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>try await group.waitForAll() waits for all tasks to finish before returning.\u003C\u002Fli>\u003C\u002Ful>\n\u003C\u002Fol>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Fairly easy. But what if you use a third-party networking SDK without native async\u002Fawait support?\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Ch2>Migrating a networking layer that uses Alamofire\u003C\u002Fh2>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"APIService bridging Alamofire to async\u002Fawait using withCheckedThrowingContinuation\" src=\"https:\u002F\u002Fs3-eu-west-2.amazonaws.com\u002Fwolfpack-digital-attachments-production\u002Fckeditor_assets\u002Fpictures\u002F777\u002Fcontent_image4.png\" style=\"width: 600px; height: 422px\">\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>These days, Alamofire ships native async\u002Fawait support (from version 5.5 onward), so you can await its response tasks directly. But the same pattern shown here is invaluable for any SDK that still uses completion handlers. The bridge is \u003Cstrong>withCheckedThrowingContinuation\u003C\u002Fstrong>:\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Col>\n\u003Cul>\u003Cli>Wrap the completion-handler API in \u003Cstrong>await withCheckedThrowingContinuation\u003C\u002Fstrong>. It bridges Swift's async\u002Fawait model with older asynchronous APIs.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>On a \u003Cstrong>success\u003C\u002Fstrong> result, call continuation.resume(returning:).\u003C\u002Fli>\u003C\u002Ful>\n\u003Cul>\u003Cli>On a \u003Cstrong>failure\u003C\u002Fstrong> result, call continuation.resume(throwing:).\u003C\u002Fli>\u003C\u002Ful>\n\u003C\u002Fol>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Ch2>Wrapping up\u003C\u002Fh2>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>Code cleanliness and readability matter as much as keeping your apps up to date with the latest tools. Adopting async\u002Fawait pairs nicely with refactoring older code and giving legacy iOS apps a fresh start. Need a hand modernizing your app? Our \u003Ca href=\"https:\u002F\u002Fwww.wolfpack-digital.com\u002Fservices\u002Fmobile-development\u002Fios\" target=\"_blank\">iOS development team\u003C\u002Fa> can help, and you can \u003Ca href=\"https:\u002F\u002Fwww.wolfpack-digital.com\u002Fblogposts?page=1&amp;categories=mobile-development\" target=\"_blank\">read more of our mobile development articles\u003C\u002Fa>.\u003C\u002Fp>\u003Cp>\r\n\r\n\u003C\u002Fp>\u003Cp>And to end with a lightly altered proverb: \u003Cem>\"Good things come to those who await.\"\u003C\u002Fem>\u003C\u002Fp>","migrating-your-project-to-the-new-swift-concurrency-using-async-await",[78,81,84,87,90,93,96,99],{"style":79,"url":80},"640","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fblogpost\u002F263\u002Ffeatured_image\u002F640\u002Fasync-await.webp",{"style":82,"url":83},"768","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fblogpost\u002F263\u002Ffeatured_image\u002F768\u002Fasync-await.webp",{"style":85,"url":86},"1024","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fblogpost\u002F263\u002Ffeatured_image\u002F1024\u002Fasync-await.webp",{"style":88,"url":89},"1366","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fblogpost\u002F263\u002Ffeatured_image\u002F1366\u002Fasync-await.webp",{"style":91,"url":92},"1600","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fblogpost\u002F263\u002Ffeatured_image\u002F1600\u002Fasync-await.webp",{"style":94,"url":95},"1920","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fblogpost\u002F263\u002Ffeatured_image\u002F1920\u002Fasync-await.webp",{"style":97,"url":98},"thumb","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fblogpost\u002F263\u002Ffeatured_image\u002Fthumb\u002Fasync-await.webp",{"style":100,"url":101},"original","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fblogpost\u002F263\u002Ffeatured_image\u002Foriginal\u002Fasync-await.webp",{"title":103,"description":104,"keywords":105,"contact_form:title":106,"contact_form:cta":107,"og:site_name":68,"og:type":108,"og:locale":69,"twitter:card":109,"twitter:site":70,"twitter:creator":70,"og:title":103,"og:image:alt":110,"twitter:title":103,"og:description":104,"twitter:description":104},"Swift Concurrency: async\u002Fawait | Wolfpack Digital","A practical guide to migrating an iOS project to Swift concurrency with async\u002Fawait, including multiple API calls, task groups, and Alamofire.","swift concurrency, swift async await, async await ios, swift structured concurrency, ios development, wolfpack digital","contact us","send message","article","summary_large_image","Xcode Project Navigator showing the AsyncAwait iOS sample project structure, by Wolfpack Digital","10 min",32,[],"Jul 10, 2023",[116],"mobile-development","2023-07-10T10:54:21.000Z",null,[120,121,122,123,124],"Async\u002Fawait, introduced in Swift 5.5, is now a mature, standard part of Swift concurrency.","Migrating removes nested completion handlers and produces cleaner, shorter, safer code.","Mark functions async throws and call them with try await; use MainActor.run for UI updates.","Use withThrowingTaskGroup to run and await multiple API calls concurrently.","Alamofire now has native async support; use withCheckedThrowingContinuation to bridge any SDK that still uses completion handlers.",[126,129,132,135],{"answer":127,"question":128},"Async\u002Fawait is part of Swift's structured concurrency model, introduced in Swift 5.5. It lets you write asynchronous code that reads like synchronous code, replacing nested completion handlers with async functions and await statements.","What is async\u002Fawait in Swift?",{"answer":130,"question":131},"Awaited network calls run off the main thread, so wrap UI updates in await MainActor.run (or mark the code with @MainActor). This switches to the main thread before you touch published properties or UI state.","How do I update the UI after an async call in Swift?",{"answer":133,"question":134},"Use withThrowingTaskGroup(of:) to add a child task per item and await them together with group.waitForAll(). For a few independent calls, you can also use async let bindings.","How can I run multiple async API calls concurrently?",{"answer":136,"question":137},"Yes. Alamofire has shipped native async\u002Fawait support since version 5.5, so you can await its response tasks directly. For any SDK that still uses completion handlers, wrap the call in withCheckedThrowingContinuation to bridge it into async\u002Fawait.","Can I use async\u002Fawait with Alamofire?","2026-07-06T12:40:38.304Z",false,"https:\u002F\u002Fwww.wolfpack-digital.com\u002Fblogposts\u002Fmigrating-your-project-to-the-new-swift-concurrency-using-async-await",[142],{"id":143,"author":144,"short_description":145,"role":146,"avatar_urls":147,"cover_urls":155,"linkedin_link":174,"instagram_link":40,"x_link":40,"meta_tags":175,"last_published_at":117,"same_as":177},62,"Bianca","Bianca has a bachelor’s degree in Computer Science and almost 7 years of experience working as an iOS developer. Besides developing awesome, visually rich apps, she loves playing the piano, drawing, playing video games, cooking, and especially baking.","iOS Developer",[148,150,153],{"style":97,"url":149},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Favatar\u002Fthumb\u002Fimage%20%2868%29.webp",{"style":151,"url":152},"medium","https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Favatar\u002Fmedium\u002Fimage%20%2868%29.webp",{"style":100,"url":154},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Favatar\u002Foriginal\u002Fimage%20%2868%29.webp",[156,158,160,162,164,166,168,170,172],{"style":79,"url":157},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002F640\u002FBianca.webp",{"style":82,"url":159},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002F768\u002FBianca.webp",{"style":85,"url":161},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002F1024\u002FBianca.webp",{"style":88,"url":163},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002F1366\u002FBianca.webp",{"style":91,"url":165},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002F1600\u002FBianca.webp",{"style":94,"url":167},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002F1920\u002FBianca.webp",{"style":97,"url":169},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002Fthumb\u002FBianca.webp",{"style":151,"url":171},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002Fmedium\u002FBianca.webp",{"style":100,"url":173},"https:\u002F\u002Fcdn.wolfpack-digital.com\u002Fstore\u002Fpublisher\u002F62\u002Fcover_image\u002Foriginal\u002FBianca.webp","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fbianca-popovici-28b62aa2\u002F",{"title":144,"description":146,"keywords":40,"contact_form:title":106,"contact_form:cta":107,"og:site_name":68,"og:type":176,"og:locale":69,"twitter:card":109,"twitter:site":70,"twitter:creator":70},"website",[174]]