<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Actor &#8211; Wade Tregaskis</title>
	<atom:link href="https://wadetregaskis.com/tags/actor/feed/" rel="self" type="application/rss+xml" />
	<link>https://wadetregaskis.com</link>
	<description></description>
	<lastBuildDate>Fri, 01 Mar 2024 19:55:35 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://wadetregaskis.com/wp-content/uploads/2016/03/Stitch-512x512-1-256x256.png</url>
	<title>Actor &#8211; Wade Tregaskis</title>
	<link>https://wadetregaskis.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">226351702</site>	<item>
		<title>Beware of specifying isolation requirements for whole protocols</title>
		<link>https://wadetregaskis.com/beware-of-specifying-isolation-requirements-for-whole-protocols/</link>
					<comments>https://wadetregaskis.com/beware-of-specifying-isolation-requirements-for-whole-protocols/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Fri, 01 Mar 2024 19:55:32 +0000</pubDate>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Actor]]></category>
		<category><![CDATA[isolation]]></category>
		<category><![CDATA[protocol]]></category>
		<category><![CDATA[Swift]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=7829</guid>

					<description><![CDATA[Matt Massicotte has a well-written, brief introduction to isolation in Swift. But it mostly just enumerates the state of things, without offering much guidance. One pitfall in particular is important to call out, regarding isolated protocols. These might seem pretty similar &#8211; you&#8217;d be forgiven for assuming it&#8217;s just a convenience to put @MainActor on&#8230; <a class="read-more-link" href="https://wadetregaskis.com/beware-of-specifying-isolation-requirements-for-whole-protocols/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p><a href="https://www.massicotte.org/about" data-wpel-link="external" target="_blank" rel="external noopener">Matt Massicotte</a> has <a href="https://www.massicotte.org/intro-to-isolation" data-wpel-link="external" target="_blank" rel="external noopener">a well-written, brief introduction to isolation in Swift</a>.  But it mostly just enumerates the state of things, without offering much guidance.  One pitfall in particular is important to call out, regarding isolated protocols.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #000000">@</span><span style="color: #001080">MainActor</span></span>
<span class="line"><span style="color: #001080">protocol</span><span style="color: #000000"> </span><span style="color: #001080">GloballyIsolatedProtocol</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">method</span><span style="color: #000000">()</span></span>
<span class="line"><span style="color: #000000">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #001080">protocol</span><span style="color: #000000"> </span><span style="color: #001080">PerMemberIsolatedProtocol</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    @</span><span style="color: #001080">MainActor</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">method</span><span style="color: #000000">()</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<p>These might seem pretty similar &#8211; you&#8217;d be forgiven for assuming it&#8217;s just a convenience to put <code>@MainActor</code> on the protocol overall rather than having to repeat it for every member of the protocol.  Less error-prone, too.</p>



<p>But, you generally shouldn&#8217;t do that.  They are <em>not</em> equivalent.</p>



<p>The first form is not merely saying that all the members of the protocol require a certain isolation, but that the <em>type</em> that conforms to the protocol must have that isolation.  The <em>whole</em> type.</p>



<p>And you might think:  …so what?</p>



<p>And indeed it <em>seems</em> like it&#8217;s fine:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #000000">@</span><span style="color: #001080">MainActor</span></span>
<span class="line"><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">doStuff</span><span style="color: #000000">() {}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #0000FF">class</span><span style="color: #000000"> </span><span style="color: #267F99">ClassA</span><span style="color: #000000">: </span><span style="color: #267F99">GloballyIsolatedProtocol</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">method</span><span style="color: #000000">() {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #795E26">doStuff</span><span style="color: #000000">()</span></span>
<span class="line"><span style="color: #000000">    }</span></span>
<span class="line"><span style="color: #000000">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #0000FF">class</span><span style="color: #000000"> </span><span style="color: #267F99">ClassB</span><span style="color: #000000">: </span><span style="color: #267F99">PerMemberIsolatedProtocol</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">method</span><span style="color: #000000">() {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #795E26">doStuff</span><span style="color: #000000">()</span></span>
<span class="line"><span style="color: #000000">    }</span></span>
<span class="line"><span style="color: #000000">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #008000">// ✅ Everything is hunky-dory as far as the compiler is concerned.</span></span></code></pre></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>🤔 Some folks might think it&#8217;s a bit dangerously magical that <code>ClassA</code> is secretly <code>@MainActor</code> now by simply conforming to the protocol, even though nothing in the class&#8217;s declaration actually says that &#8211; and likewise for <code>method</code> for <code>ClassB</code>.  That&#8217;s largely a separate topic.  But okay, it makes a <em>kind</em> of sense at least…</p>
</div></div>



<p>But try to use actors instead of classes, and see how it all falls apart:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #001080">actor</span><span style="color: #000000"> ActorA: </span><span style="color: #001080">GloballyIsolatedProtocol</span><span style="color: #000000"> { </span><span style="color: #008000">// ❌ Actor &#39;ActorA&#39; cannot conform to global actor isolated protocol &#39;GloballyIsolatedProtocol&#39;</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">method</span><span style="color: #000000">() {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #795E26">doStuff</span><span style="color: #000000">() </span><span style="color: #008000">// ❌ Call to main actor-isolated global function &#39;doStuff()&#39; in a synchronous actor-isolated context</span></span>
<span class="line"><span style="color: #000000">    }</span></span>
<span class="line"><span style="color: #000000">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #001080">actor</span><span style="color: #000000"> ActorB: </span><span style="color: #001080">PerMemberIsolatedProtocol</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">method</span><span style="color: #000000">() { </span><span style="color: #008000">// ❌ Actor-isolated instance method &#39;method()&#39; cannot be used to satisfy main actor-isolated protocol requirement</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #795E26">doStuff</span><span style="color: #000000">() </span><span style="color: #008000">// ❌ Call to main actor-isolated global function &#39;doStuff()&#39; in a synchronous actor-isolated context</span></span>
<span class="line"><span style="color: #000000">    }</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<p>All these error messages are correct, even if they may be surprising at first.  You might even say:  so what?  That&#8217;s working as expected.</p>



<p>The problem is that there is <em>nothing</em> an actor can do to conform to <code>GloballyIsolatedProtocol</code>.  It is an actor-hostile protocol.  It is <em>unusable</em> by actors.</p>



<p>Whereas <code>PerMemberIsolatedProtocol</code> <em>can</em> be used by an actor:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #001080">actor</span><span style="color: #000000"> ActorB: </span><span style="color: #001080">PerMemberIsolatedProtocol</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    @</span><span style="color: #001080">MainActor</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">method</span><span style="color: #000000">() {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #795E26">doStuff</span><span style="color: #000000">()</span></span>
<span class="line"><span style="color: #000000">    }</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<p>Given that protocols are most often just used to express an interface requirement &#8211; e.g. for delegates, data sources, codability, etc &#8211; there is usually no reason why actors shouldn&#8217;t be allowed to conform to them.  Even if the protocol does have some isolation requirements, there&#8217;s no technical reason an actor can&#8217;t abide by those <em>if it&#8217;s given the chance</em>.</p>



<p>This leads into a more complicated aspect of isolation in Swift, regarding how actors aren&#8217;t necessarily restricted to their own isolation domain.  They can have methods and properties that are not isolated at all, or isolated to a <em>different</em> domain.  In Swift 6 they&#8217;ll even be able to have methods which are isolated <em>to different actors</em>!</p>



<p>So don&#8217;t make the mistake of assuming actors can only ever be off in their own isolated worlds.  And don&#8217;t needlessly exclude them from supporting your protocols.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/beware-of-specifying-isolation-requirements-for-whole-protocols/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7829</post-id>	</item>
		<item>
		<title>Performing a delayed and/or repeating operation in a Swift Actor</title>
		<link>https://wadetregaskis.com/performing-a-delayed-and-or-repeating-operation-in-a-swift-actor/</link>
					<comments>https://wadetregaskis.com/performing-a-delayed-and-or-repeating-operation-in-a-swift-actor/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Sat, 30 Jul 2022 19:50:07 +0000</pubDate>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Howto]]></category>
		<category><![CDATA[Actor]]></category>
		<category><![CDATA[Concurrency]]></category>
		<category><![CDATA[Dispatch]]></category>
		<category><![CDATA[DispatchQueue]]></category>
		<category><![CDATA[Executor]]></category>
		<category><![CDATA[Grand Central Dispatch]]></category>
		<category><![CDATA[RunLoop]]></category>
		<category><![CDATA[Structured Concurrency]]></category>
		<category><![CDATA[Swift]]></category>
		<category><![CDATA[Task]]></category>
		<category><![CDATA[Thread]]></category>
		<category><![CDATA[Timer]]></category>
		<guid isPermaLink="false">https://blog.wadetregaskis.com/?p=5155</guid>

					<description><![CDATA[Say you want to perform some operation after a delay, and/or at regular intervals, inside a Swift actor &#8211; maybe your actor represents a weather station and you want to periodically fetch the latest weather information, automatically. How do you do that? You could punt the problem to some other code, outside the actor &#8211;&#8230; <a class="read-more-link" href="https://wadetregaskis.com/performing-a-delayed-and-or-repeating-operation-in-a-swift-actor/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>Say you want to perform some operation after a delay, and/or at regular intervals, inside a Swift actor &#8211; maybe your actor represents a weather station and you want to periodically fetch the latest weather information, automatically.  How do you do that?</p>



<p>You <em>could</em> punt the problem to some other code, outside the actor &#8211; i.e. make something <em>else</em> periodically call some method on the actor.  Sometimes this is a suitable approach, but sometimes you just want your actor to be self-contained and not require external aid.  And if the work takes time anyway (e.g. network activity) what&#8217;s the point of having some external entity calling in and having to wait on your actor &#8211; easier if your actor just notifies the external entity whenever new data is available.</p>



<h2 class="wp-block-heading">Timer ❌</h2>



<p>You might think to just use <a href="https://developer.apple.com/documentation/foundation/timer" data-type="URL" data-id="https://developer.apple.com/documentation/foundation/timer" data-wpel-link="external" target="_blank" rel="external noopener"><code>Timer</code></a> (formerly <code>NSTimer</code>) &#8211; and most of the internet would strongly encourage you to do so, based on the search results you&#8217;ll find for this topic.</p>



<p>Except it doesn&#8217;t work.</p>



<p>Timer relies on <a href="https://developer.apple.com/documentation/foundation/runloop/" data-type="URL" data-id="https://developer.apple.com/documentation/foundation/runloop/" target="_blank" rel="noreferrer noopener external" data-wpel-link="external"><code>RunLoop</code></a> (<code>NSRunLoop</code>) to actually schedule itself and be executed.  <code>RunLoop</code>s are <em>normally</em> created automatically in most cases and kind of just work magically in the background.</p>



<p>Actors don&#8217;t have runloops.  More accurately &#8211; the magical, mutually-exclusive context in which an actor runs is not a <code>RunLoop</code> and does not interact with <code>RunLoop</code>s.  Actors use a relatively new <a href="https://developer.apple.com/documentation/swift/executor/" target="_blank" rel="noreferrer noopener external" data-wpel-link="external"><code>Executor</code></a> class family, but at least for now (2022) those are basically useless &#8211; literally the only method they have is to add a task to be executed as soon as possible. They provide no way to schedule a task after a delay.</p>



<p>Confusingly, if you access <a href="https://developer.apple.com/documentation/foundation/runloop/1412291-current" data-type="URL" data-id="https://developer.apple.com/documentation/foundation/runloop/1412291-current" target="_blank" rel="noreferrer noopener external" data-wpel-link="external"><code>RunLoop.current</code></a> from an actor context, it <em>will</em> return some non-nil value, but it&#8217;s useless because nothing ever <em>runs</em> that particular <code>RunLoop</code>.  And how would you run it yourself &#8211; calling its <a href="https://developer.apple.com/documentation/foundation/runloop/1412430-run" data-type="URL" data-id="https://developer.apple.com/documentation/foundation/runloop/1412430-run" target="_blank" rel="noreferrer noopener external" data-wpel-link="external">run</a> method from within the actor&#8217;s context would block the actor indefinitely and cause deadlock.</p>



<p>You could use the <a rel="noreferrer noopener external" href="https://developer.apple.com/documentation/foundation/runloop/1418388-main/" data-type="URL" data-id="https://developer.apple.com/documentation/foundation/runloop/1418388-main/" target="_blank" data-wpel-link="external">main</a> runloop that most Swift apps have by default, but you shouldn&#8217;t &#8211; that main runloop is intended for user interaction <em>only</em>.  You should never put random background tasks on it, as they can interfere with your UI and make your app stutter.</p>



<p>You could spawn your own <a href="https://developer.apple.com/documentation/foundation/thread" data-type="URL" data-id="https://developer.apple.com/documentation/foundation/thread" target="_blank" rel="noreferrer noopener external" data-wpel-link="external"><code>Thread</code></a> to actually run a <code>RunLoop</code>, but it&#8217;s unsafe &#8211; you cannot interact with any runloop except the <em>current</em> runloop &#8211; i.e. you have to be in a runloop in order to touch it &#8211; and you can&#8217;t get <em>into</em> such a runloop in an easy way from an actor context.  Seemingly obvious and innocuous methods like calling <code>RunLoop.current</code> from actor context are dangerous because they&#8217;re not guaranteed to return the <em>same</em> runloop each time.  Instead, you have to explicitly bridge to the runloop via some bespoke message system that you have to pre-install into that runloop.  Ick.</p>



<p>It&#8217;s also very inefficient, if you don&#8217;t actually need to use a whole CPU core most of the time &#8211; you&#8217;ll need a dedicated thread for every actor instance, and threads aren&#8217;t completely free to create &amp; maintain &#8211; plus there&#8217;s a limit to how many you can have alive at one time.</p>



<h2 class="wp-block-heading">Dispatch ✔️</h2>



<p>A better approach is to use <a href="https://developer.apple.com/documentation/dispatch" data-type="URL" data-id="https://developer.apple.com/documentation/dispatch" target="_blank" rel="noreferrer noopener external" data-wpel-link="external">Dispatch</a> (formerly Grand Central Dispatch) &#8211; specifically the convenient methods on <a href="https://developer.apple.com/documentation/dispatch/dispatchqueue" data-type="URL" data-id="https://developer.apple.com/documentation/dispatch/dispatchqueue" target="_blank" rel="noreferrer noopener external" data-wpel-link="external"><code>DispatchQueue</code></a> that allow you to set up delayed and/or scheduled tasks.  There&#8217;s the various async… methods for doing something once after a certain time period, and also schedule… methods which also support recurring, cancellable timers.  Granted they aren&#8217;t tied to the actor&#8217;s context &#8211; you still have to bridge back into the actor via <a href="https://developer.apple.com/documentation/swift/task/" data-type="URL" data-id="https://developer.apple.com/documentation/swift/task/" target="_blank" rel="noreferrer noopener external" data-wpel-link="external"><code>Task</code></a> or similar &#8211; but at least they actually work.</p>



<p>e.g.:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #0000FF">let</span><span style="color: #000000"> timer = DispatchQueue</span></span>
<span class="line"><span style="color: #000000">    .</span><span style="color: #795E26">global</span><span style="color: #000000">(</span><span style="color: #795E26">qos</span><span style="color: #000000">: .</span><span style="color: #001080">utility</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">    .</span><span style="color: #795E26">schedule</span><span style="color: #000000">(</span><span style="color: #795E26">after</span><span style="color: #000000">: DispatchQueue.</span><span style="color: #795E26">SchedulerTimeType</span><span style="color: #000000">(.</span><span style="color: #795E26">now</span><span style="color: #000000">()),</span></span>
<span class="line"><span style="color: #000000">              </span><span style="color: #795E26">interval</span><span style="color: #000000">: .</span><span style="color: #795E26">seconds</span><span style="color: #000000">(refreshInterval),</span></span>
<span class="line"><span style="color: #000000">              </span><span style="color: #795E26">tolerance</span><span style="color: #000000">: .</span><span style="color: #795E26">seconds</span><span style="color: #000000">(refreshInterval / </span><span style="color: #098658">5</span><span style="color: #000000">)) { [</span><span style="color: #0000FF">weak</span><span style="color: #000000"> </span><span style="color: #0000FF">self</span><span style="color: #000000">] </span><span style="color: #AF00DB">in</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #AF00DB">guard</span><span style="color: #000000"> </span><span style="color: #0000FF">let</span><span style="color: #000000"> </span><span style="color: #0000FF">self</span><span style="color: #000000"> </span><span style="color: #AF00DB">else</span><span style="color: #000000"> { </span><span style="color: #AF00DB">return</span><span style="color: #000000"> }</span></span>
<span class="line"><span style="color: #000000">    Task { </span><span style="color: #AF00DB">await</span><span style="color: #000000"> </span><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #795E26">getLatestMeasurement</span><span style="color: #000000">() } </span><span style="color: #008000">// Trampoline back into the actor context.</span></span>
<span class="line"><span style="color: #000000">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #008000">// Keep &quot;timer&quot; around as e.g. a member variable if you want to be able to cancel it.</span></span></code></pre></div>



<p>If you use the schedule… methods you may need to import Combine, as the <code>Cancellable</code> type that they return is actually defined in Combine.  But you don&#8217;t have to actually use Combine otherwise.</p>



<h2 class="wp-block-heading">Structured Concurrency (<code>Task</code>) ✔️</h2>



<p>An alternative approach is to just use Swift Concurrency primitives.  This is arguably &#8220;purer&#8221; &#8211; no need to pull in the Dispatch &amp; Combine libraries &#8211; but requires a bit more manual labour if you need to support cancellation.</p>



<p>Basically you can create a new <code>Task</code> which just sits in a loop running the desired operation endlessly (or until cancelled), manually sleeping between executions.</p>



<p>e.g.:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #001080">timer</span><span style="color: #000000"> = </span><span style="color: #795E26">Task</span><span style="color: #000000">(</span><span style="color: #795E26">priority</span><span style="color: #000000">: .</span><span style="color: #001080">utility</span><span style="color: #000000">) { [</span><span style="color: #0000FF">weak</span><span style="color: #000000"> </span><span style="color: #0000FF">self</span><span style="color: #000000">] </span><span style="color: #AF00DB">in</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #AF00DB">while</span><span style="color: #000000"> !Task.</span><span style="color: #001080">isCancelled</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #AF00DB">guard</span><span style="color: #000000"> </span><span style="color: #0000FF">let</span><span style="color: #000000"> </span><span style="color: #0000FF">self</span><span style="color: #000000"> </span><span style="color: #AF00DB">else</span><span style="color: #000000"> { </span><span style="color: #AF00DB">return</span><span style="color: #000000"> }</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #AF00DB">await</span><span style="color: #000000"> </span><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #795E26">getLatestMeasurement</span><span style="color: #000000">()</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #AF00DB">try</span><span style="color: #000000">? </span><span style="color: #AF00DB">await</span><span style="color: #000000"> Task.</span><span style="color: #795E26">sleep</span><span style="color: #000000">(</span><span style="color: #795E26">nanoseconds</span><span style="color: #000000">: </span><span style="color: #267F99">UInt64</span><span style="color: #000000">(refreshInterval * </span><span style="color: #098658">1_000_000_000</span><span style="color: #000000">))</span></span>
<span class="line"><span style="color: #000000">    }</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<p>It doesn&#8217;t look too bad, but keep in mind this loses some important functionality vs the Dispatch approach &#8211; there&#8217;s no way to specify a tolerance to the timer, so this is not as good for energy efficiency (in cases where you don&#8217;t need <em>exact</em> timing, which is most cases).</p>



<p>There is <a href="https://developer.apple.com/documentation/swift/task/sleep(until:tolerance:clock:)" data-type="URL" data-id="https://developer.apple.com/documentation/swift/task/sleep(until:tolerance:clock:)" target="_blank" rel="noreferrer noopener external" data-wpel-link="external">a new variant of the <code>Task.sleep</code> method</a> potentially coming in iOS 16, macOS 13, etc which does allow you to specify a tolerance, but that of course requires a minimum deployment target of essentially 2023 or later.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/performing-a-delayed-and-or-repeating-operation-in-a-swift-actor/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5155</post-id>	</item>
	</channel>
</rss>
