 <p>Try to perform the action in a background-queue using the following code:</p> <pre><code>SwiftSpinner.show("Generating new calendar for \(forYear)", animated: true) dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { let calendar = generateCalendarFor(forYear) print("GENERATED NEW calendar for \(forYear)") dispatch_async(dispatch_get_main_queue(), { SwiftSpinner.show("Saving calendar", animated: false) }) saveNew(calendar, year: forYear) dispatch_async(dispatch_get_main_queue(), { SwiftSpinner.hide() onCompletion(calendar) }) }) </code></pre> <p>What you do here:</p> <ul> <li>you create a background-queue</li> <li>create the calendar</li> <li>update the UI from the main-queue (<code>dispatch_async(dispatch_get_main_queue(), { SwiftSpinner.show("Saving calendar", animated: false) })</code> (main-queue is important because the UI shpuld only be modified from the main-queue)</li> <li>save the calendar (in the background-queue again)</li> <li>call a custom function (here I named it <code>onCompletion</code> in the main-queue which does something with the calendar (replaces <code>return calendar</code>)</li> </ul> <p>You should make sure that your UI-buttons etc. are disabled before <code>dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { ... })</code> gets called and enabled again in <code>onCompletion</code> else the user would be able to press some buttons while your app is working (and maybe change some data used by the queue -> not good).</p> <p><strong>Why:</strong> The UI is updated from the main-queue, but usually not immediately after you call the code to update it; if you block the main-queue, your UI cannot be updated. So we do the work in a background-queue so your main-queue can update the UI.</p> <p><strong>In detail:</strong> You call <code>dispatch_async</code> (from GrandCentralDispatch) which creates a new queue with the priority <code>QOS_CLASS_USER_INITIATED</code> (~normal priority). Then it passes the code in the curly braces to this queue; the OS will execute the queue in a separate thread. Because the UI must only be modified from the main-queue, we pass the code that updates the UI (<code>SwiftSpinner.show("Saving calendar", animated: false)</code>) to the main-queue by using <code>dispatch_async</code> again.</p> <p>The use of a completion-function is necessary because the code/queue is executed in the background and independently from <code>getOrCreateCalendar</code>; your function probably returns before the queue is completed and the calendar created and saved.</p>