<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
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/">
	<channel>
		<title>Combine’s What Makes SwiftUI Really Shine | Infinum</title>
		<atom:link href="https://infinum.com/blog/combine-makes-swiftui-shine/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/combine-makes-swiftui-shine/</link>
		<description>Building digital products</description>
		<lastBuildDate>Wed, 29 Apr 2026 14:21:05 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>7871https://infinum.com/uploads/2019/07/combine-makes-swiftui-shine-0.webp</url>
				</image>
				<title>Combine’s What Makes SwiftUI Really Shine</title>
				<link>https://infinum.com/blog/combine-makes-swiftui-shine/</link>
				<pubDate>Thu, 18 Jul 2019 13:05:00 +0000</pubDate>
				<dc:creator>Krešimir Valjevac</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/combine-makes-swiftui-shine/</guid>
				<description>
					<![CDATA[<p>We still haven’t decided on what’s the best approach to SwiftUI’s declarative way of building UI architecture-wise.</p>
<p>The post <a href="https://infinum.com/blog/combine-makes-swiftui-shine/">Combine’s What Makes SwiftUI Really Shine</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-446"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-94'
	>
	It’s time to start catching up with <em>Combine</em>!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-96">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-97'
	>
	If you’ve been with me and remember the <a href="https://infinum.com/blog/swiftui-is-here-to-knock-uikit-out-of-its-shoes/">initial breakdown using SwiftUI</a>, here’s what I wanted to do:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-99">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-100'
	>
	<li>Make a List</li><li>Make a Row for that List</li><li>Create a view model</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-102">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-103'
	>
	We still haven’t decided on what’s the best approach to <em>SwiftUI’s</em> declarative way of building UI architecture-wise, but it seems to be leaning heavily towards <em>MVVM</em>, or at least some variant of it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-106'
	>
	Since it seems pretty natural to use, we’re going with that.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-108">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-109'
	>
	Creating the ViewModel</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-111">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-112'
	>
	We need to start off with several things in mind:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-114">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-115'
	>
	<li>How to represent the <em>model</em> in the <em>view</em></li><li>How to update the <em>model</em> when text changes</li><li>How to update the <em>view</em> for <em>model</em> changes</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-119"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-117">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-118'
	>
	First things first, the view needs to read values from the state of the view model. The model will be updating its state when it receives events from the <code>URLSession.DataTaskPublisher</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-122"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-120">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-121'
	>
	If you’re familiar with <em>RxSwift</em>, you’ll know that you can achieve that by binding streams of data to UI elements.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-125"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-123">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-124'
	>
	In the case of <em>SwiftUI</em>, it’ll actually re-render the component that needs to be updated. So, when building a list of rows and that list updates, the UI will end up adjusting itself to accommodate for the changes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-128"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-126">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-127'
	>
	With all that in mind, let’s make a model which represents a single <em>GitHub</em> repository.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-131"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-129">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-130'
	>
	Repository model</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-133"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">struct Repository</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Identifiable</span><span class="token">, </span><span class="token" style="color: #6f42c1;">Decodable </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let id:</span><span class="token"> </span><span class="token" style="color: #005cc5;">Int</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let name:</span><span class="token"> </span><span class="token" style="color: #005cc5;">String</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let fullName:</span><span class="token"> </span><span class="token" style="color: #005cc5;">String</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let description:</span><span class="token"> </span><span class="token" style="color: #005cc5;">String</span><span class="token" style="color: #d73a49;">?</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let stargazersCount:</span><span class="token"> </span><span class="token" style="color: #005cc5;">Int</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-136"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-134">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-135'
	>
	A simple struct with some attributes that conforms to <code>Decodable</code>. Those of you with a keen eye might’ve noticed something new—and that’s a protocol called <code>Identifiable</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-139"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-137">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-138'
	>
	The only requirement of the protocol is that the object has an <code>id</code>, which is then used by <code>Equatable</code> under the hood. That’s great! But… where is it identified? <em>SwiftUI</em> uses it for its <code>List</code> element which does diffing, insertion and deletion for us.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-142"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-140">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-141'
	>
	How cool is that?! No more headaches with index paths. ?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-145"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-143">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-144'
	>
	Repository view model</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-148"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-146">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-147'
	>
	The single most important thing to do is to conform to the <code>BindableObject</code> protocol. The object uses that to notify the framework when it receives changes. Changes are then sent to the view, which then updates the layout.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-153"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-149">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-150'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-151'
	>
	Note: If you’ve used RxSwift, AnyPublisher in essence is the well known asObservable() operator.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-155"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token">class RepositoryViewModel</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">BindableObject </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> BindableObject conformance</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let didChange:</span><span class="token"> AnyPublisher</span><span class="token">&lt;</span><span class="token" style="color: #005cc5;">Void</span><span class="token">, </span><span class="token" style="color: #005cc5;">Never</span><span class="token">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Data model</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var repositories:</span><span class="token"> </span><span class="token">[</span><span class="token">Repository</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">init</span><span class="token">(</span><span class="token">repositories</span><span class="token">: </span><span class="token">[</span><span class="token">Repository</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> []</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #005cc5;">self</span><span class="token">.</span><span class="token">repositories</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> repositories
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-158"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-156">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-157'
	>
	To satisfy the protocol, we need the <code>didChange</code> property, which is typed as <code>AnyPublisher&lt;Void, Never&gt;</code>. It’s pretty cool that we don’t need a concrete type, the framework only expects us to signal when there are updates in the pipeline!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-161"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-159">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-160'
	>
	Since we’re also binding to the UI, errors need to be handled before passing values to the publisher. Hence the second type, which is represented as <code>Never</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-164"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-162">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-163'
	>
	View Model integration</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-167"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-165">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-166'
	>
	I’ll concentrate only on the <code>ListView</code> and the <code>RepositoryRowView</code>, since the implementation is exactly the same across all of them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-170"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-168">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-169'
	>
	<li>ListView</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-172"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">struct ListView</span><span class="token"> </span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">@ObjectBinding</span><span class="token"> </span><span class="token">var viewModel:</span><span class="token"> RepositoryViewModel</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">@State</span><span class="token"> </span><span class="token" style="color: #d73a49;">var</span><span class="token"> text </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var body:</span><span class="token"> </span><span class="token" style="color: #d73a49;">some</span><span class="token"> View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">NavigationView</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token">TextField(</span><span class="token">$text</span><span class="token">, </span><span class="token">placeholder:</span><span class="token"> </span><span class="token">Text(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Search...</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">               .</span><span class="token">textFieldStyle(</span><span class="token">.</span><span class="token">roundedBorder</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">               .</span><span class="token">padding(</span><span class="token">[.</span><span class="token">leading</span><span class="token">, </span><span class="token">.</span><span class="token">trailing</span><span class="token">], </span><span class="token" style="color: #005cc5;">20</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token">List(</span><span class="token">viewModel.</span><span class="token">repositories</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token"> repository </span><span class="token" style="color: #d73a49;">in</span><span class="token">
</span></span><span class="line"><span class="token">               </span><span class="token">RepositoryRowView(</span><span class="token">repository:</span><span class="token"> repository</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">listStyle(</span><span class="token">.</span><span class="token">grouped</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">environment(</span><span class="token">\.</span><span class="token">defaultMinListRowHeight</span><span class="token">, </span><span class="token" style="color: #005cc5;">50</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">navigationBarTitle(</span><span class="token">.</span><span class="token" style="color: #d73a49;">init</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">GitHub search</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">       .</span><span class="token">colorScheme(</span><span class="token">.</span><span class="token">dark</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">#</span><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token">DEBUG</span><span class="token">
</span></span><span class="line"><span class="token">struct ListView_Previews</span><span class="token"> </span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">PreviewProvider </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">static</span><span class="token"> </span><span class="token">var previews:</span><span class="token"> </span><span class="token" style="color: #d73a49;">some</span><span class="token"> View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">ListView(</span><span class="token">viewModel:</span><span class="token"> .</span><span class="token" style="color: #d73a49;">init</span><span class="token">(</span><span class="token">repositories:</span><span class="token"> </span><span class="token">RepositoriesMock(</span><span class="token">)</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">#</span><span class="token" style="color: #d73a49;">endif</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-173">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-174'
	>
	<code>ListView</code> requires a few simple changes. Instead of a fixed range that we passed to the <code>List</code> initially, we’re now passing the <code>repositories</code> property of the model.<br>If <code>Repository</code> is not conforming to the <code>Identifiable</code> protocol, a convoluted error might pop up in this moment, so double check that in case of any weirdness.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-180"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-176">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-177'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-178'
	>
	Note: RepositoriesMock is a simple array of hardcoded repositories, which is passed for preview purposes. This enables you to see your data in the handy preview window on the right of the editor.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-183"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-181">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-182'
	>
	All that’s left to do now is to add the <code>Repository</code> to the rest of the subviews.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-186"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-184">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-185'
	>
	<li>RepositoryRowView</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-188"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">struct RepositoryRowView</span><span class="token"> </span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let repository:</span><span class="token"> Repository</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var body:</span><span class="token"> </span><span class="token" style="color: #d73a49;">some</span><span class="token"> View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">HStack(</span><span class="token">alignment:</span><span class="token"> .</span><span class="token">center</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token">DetailsContainerView(</span><span class="token">repository:</span><span class="token"> repository</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token">Spacer(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token">StarsContainerView(</span><span class="token">repository:</span><span class="token"> repository</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">struct RepositoryRowView_Previews</span><span class="token"> </span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">PreviewProvider </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">static</span><span class="token"> </span><span class="token">var previews:</span><span class="token"> </span><span class="token" style="color: #d73a49;">some</span><span class="token"> View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">return</span><span class="token"> </span><span class="token">RepositoryRowView(</span><span class="token">repository:</span><span class="token"> RepositoriesMock</span><span class="token">[</span><span class="token" style="color: #005cc5;">0</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-193"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-189">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-190'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-191'
	>
	Note: When you add a new view by hand, a preview won’t be generated out-of-the-box. To get it to work, simply add struct RepositoryRowView_Previews which needs to implement the PreviewProvider.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-196"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-194">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-195'
	>
	Pretty simple, right?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-199"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-197">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-198'
	>
	The exact same thing needs to be done for both the <code>DetailsContainerView</code> and the <code>StarsContainerView</code>, so I won’t dive into that.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-202"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-200">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-201'
	>
	Wrapping up the View Model</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-205"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-203">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-204'
	>
	We’ve already started by adding a publisher that’s responsible of notifying the view about updates.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-208"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-206">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-207'
	>
	What about the changes of the actual data source, that is, the repositories array inside of the view model?<br>Thankfully, <code>URLSession</code> provides a publisher just for that!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-211"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-209">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-210'
	>
	We also need to pass any text changes from the view to the view model. It then needs to initiate an API call and provide information about the update.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-214"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-212">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-213'
	>
	Taking a look at the <code>ListView</code> again, we can see the <code>@State</code> property wrapper that’s used to track text changes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-216"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">struct ListView</span><span class="token"> </span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">...</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">@State</span><span class="token"> </span><span class="token" style="color: #d73a49;">var</span><span class="token"> text </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var body:</span><span class="token"> </span><span class="token" style="color: #d73a49;">some</span><span class="token"> View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">...</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">TextField(</span><span class="token">$text</span><span class="token">, </span><span class="token">placeholder:</span><span class="token"> </span><span class="token">Text(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Search...</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">textFieldStyle(</span><span class="token">.</span><span class="token">roundedBorder</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">padding(</span><span class="token">[.</span><span class="token">leading</span><span class="token">, </span><span class="token">.</span><span class="token">trailing</span><span class="token">], </span><span class="token" style="color: #005cc5;">20</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">...</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-221"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-217">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-218'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-219'
	>
	Note: The $ symbol means that we’re mutating the state instead of passing it by value, i.e. we’re making it mutable or reference-alike.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-224"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-222">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-223'
	>
	Since we have no use of that property in the view anymore, we can move it into the model! We can use it to track changes internally and simply notify the view when we’re done.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-227"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-225">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-226'
	>
	Let’s tweak both the model and the list. We’ll start with the list since it’s simpler:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-229"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">struct ListView</span><span class="token"> </span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">@ObjectBinding</span><span class="token"> </span><span class="token">var viewModel:</span><span class="token"> RepositoryViewModel</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var body:</span><span class="token"> </span><span class="token" style="color: #d73a49;">some</span><span class="token"> View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">...</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">TextField(</span><span class="token">viewModel</span><span class="token">[</span><span class="token">\.</span><span class="token" style="color: #005cc5;">text</span><span class="token">]</span><span class="token">, </span><span class="token">placeholder:</span><span class="token"> </span><span class="token">Text(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Search...</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">textFieldStyle(</span><span class="token">.</span><span class="token">roundedBorder</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">padding(</span><span class="token">[.</span><span class="token">leading</span><span class="token">, </span><span class="token">.</span><span class="token">trailing</span><span class="token">], </span><span class="token" style="color: #005cc5;">20</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">...</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-232"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-230">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-231'
	>
	The <code>@State var text</code> was replaced by binding the text field to a keypath which points to the <code>text</code> property of the view model. Going further, let’s adjust the model now:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-234"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token">class RepositoryViewModel</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">BindableObject </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> BindableObject conformance</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let didChange:</span><span class="token"> AnyPublisher</span><span class="token">&lt;</span><span class="token" style="color: #005cc5;">Void</span><span class="token">, </span><span class="token" style="color: #005cc5;">Never</span><span class="token">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Public properties</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var repositories:</span><span class="token"> </span><span class="token">[</span><span class="token">Repository</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> []
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var text:</span><span class="token"> </span><span class="token" style="color: #005cc5;">String</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">didSet</span><span class="token"> </span><span class="token">{</span><span class="token"> _textDidChange.</span><span class="token">send(</span><span class="token">text</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Private properties</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token" style="color: #d73a49;">let</span><span class="token"> _textDidChange </span><span class="token" style="color: #d73a49;">=</span><span class="token"> PassthroughSubject</span><span class="token" style="color: #d73a49;">&lt;</span><span class="token" style="color: #005cc5;">String</span><span class="token">, </span><span class="token" style="color: #005cc5;">Never</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">var _cancellable:</span><span class="token"> Cancellable</span><span class="token" style="color: #d73a49;">?</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">init</span><span class="token">(</span><span class="token">repositories</span><span class="token">: </span><span class="token">[</span><span class="token">Repository</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> []</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #005cc5;">self</span><span class="token">.</span><span class="token">repositories</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> repositories
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-237"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-235">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-236'
	>
	This concludes all the properties necessary to make the view model work! Not so bad, right?<br>Concentrating on said properties, we can see the following:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-240"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-238">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-239'
	>
	<li><code>var text: String</code> to which we bind text changes from the view, which forwards its value to the <code>_textDidChange</code> subject</li><li><code>let _textDidChange: PassthroughSubject&lt;String, Never&gt;</code> which is a private property used to notify the view model that there were some changes in the view</li><li><code>var _cancellable: Cancellable?</code> which we can use to cancel any ongoing work</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-243"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-241">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-242'
	>
	To elaborate, for each character input in the textfield, our internal subject will get notified through the setter of the <code>text</code> variable. This then initiates an API call.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-246"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-244">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-245'
	>
	That API call is going to return a <code>cancellable</code> which we store and call on <code>deinit</code> to clean up the resources when needed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-249"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-247">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-248'
	>
	Woah, wait, what’s a <code>subject</code> now? Well, since I talked about publishers already—I can paraphrase that <em>a Subject in its most simplest term is a publisher into which you’re able to write values</em>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-252"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-250">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-251'
	>
	Remember, publishers are read-only and are strictly used to pass data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-255"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-253">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-254'
	>
	On the other hand, a subject can be used as a bridge between reactive and non-reactive code, since it’s able to receive data in its stream.<br>We’ll use that to publish text changes through the stream which will result in an API call returning the <code>Repositories</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-258"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-256">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-257'
	>
	That’s a lot to chew through, but bear with me and let’s just pour those words into code:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-260"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token">class RepositoryViewModel</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">BindableObject </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> BindableObject conformance</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">let didChange:</span><span class="token"> AnyPublisher</span><span class="token">&lt;</span><span class="token" style="color: #005cc5;">Void</span><span class="token">, </span><span class="token" style="color: #005cc5;">Never</span><span class="token">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Public properties</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var repositories:</span><span class="token"> </span><span class="token">[</span><span class="token">Repository</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> []
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">var text:</span><span class="token"> </span><span class="token" style="color: #005cc5;">String</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">didSet</span><span class="token"> </span><span class="token">{</span><span class="token"> _textDidChange.</span><span class="token">send(</span><span class="token">text</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Private properties</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token" style="color: #d73a49;">let</span><span class="token"> _textDidChange </span><span class="token" style="color: #d73a49;">=</span><span class="token"> PassthroughSubject</span><span class="token" style="color: #d73a49;">&lt;</span><span class="token" style="color: #005cc5;">String</span><span class="token">, </span><span class="token" style="color: #005cc5;">Never</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">var _cancellable:</span><span class="token"> Cancellable</span><span class="token" style="color: #d73a49;">?</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Init</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">init</span><span class="token">(</span><span class="token">repositories</span><span class="token">: </span><span class="token">[</span><span class="token">Repository</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> []</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #005cc5;">self</span><span class="token">.</span><span class="token">repositories</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> repositories
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">let</span><span class="token"> search </span><span class="token" style="color: #d73a49;">=</span><span class="token"> _textDidChange
</span></span><span class="line"><span class="token">           .</span><span class="token" style="color: #005cc5;">filter</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #d73a49;">!</span><span class="token" style="color: #005cc5;">$0</span><span class="token">.</span><span class="token" style="color: #005cc5;">isEmpty</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">debounce(</span><span class="token">for:</span><span class="token"> .</span><span class="token">seconds(</span><span class="token" style="color: #005cc5;">0.3</span><span class="token">)</span><span class="token">, </span><span class="token">scheduler:</span><span class="token"> DispatchQueue.</span><span class="token">main</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">flatMapLatest</span><span class="token"> </span><span class="token">{</span><span class="token"> RepositoryViewModel.</span><span class="token">_getRepositories(</span><span class="token">using:</span><span class="token"> </span><span class="token" style="color: #005cc5;">$0</span><span class="token">, </span><span class="token">existingRepositories:</span><span class="token"> repositories</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">share(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">       didChange </span><span class="token" style="color: #d73a49;">=</span><span class="token"> search
</span></span><span class="line"><span class="token">           .</span><span class="token" style="color: #005cc5;">map</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">_</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token"> </span><span class="token">(</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">receive(</span><span class="token">on:</span><span class="token"> DispatchQueue.</span><span class="token">main</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">eraseToAnyPublisher(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">       _cancellable </span><span class="token" style="color: #d73a49;">=</span><span class="token"> search
</span></span><span class="line"><span class="token">           .</span><span class="token">tryMap</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #d73a49;">try</span><span class="token"> </span><span class="token" style="color: #005cc5;">$0</span><span class="token">.</span><span class="token">get(</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token">catch</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">_</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token"> Publishers.</span><span class="token">Just(</span><span class="token">repositories</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">           .</span><span class="token" style="color: #005cc5;">assign</span><span class="token">(</span><span class="token">to:</span><span class="token"> \.</span><span class="token">repositories</span><span class="token">, </span><span class="token">on:</span><span class="token"> </span><span class="token" style="color: #005cc5;">self</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6a737d;">///</span><span class="token" style="color: #6a737d;"> Deinit</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">deinit</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       _cancellable</span><span class="token" style="color: #d73a49;">?</span><span class="token">.</span><span class="token">cancel(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-263"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-261">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-262'
	>
	If this is a bit intimidating, fret not—I’ll go over the operators to make it a bit easier to grasp.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-266"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-264">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-265'
	>
	What’s a flatMapLatest?</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-269"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-267">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-268'
	>
	I’ve already mentioned how we’re pushing all text changes into the <code>_textDidChange</code> subject.<br>These get sent into the <code>flatMapLatest</code> operator.<br>If you’re using the first beta of <em>Combine</em>, you won’t be able to find it—you need to make it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-272"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-270">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-271'
	>
	Essentially, <code>flatMapLatest</code> can be derived into <code>map</code> and <code>switchToLatest</code> operators. But why do we need it?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-275"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-273">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-274'
	>
	Well, <code>map</code> is the same old <code>map</code> provided in <em>Swift</em>, it maps an input to a desired output. We need that to map the search <code>String</code> into an API call returning <code>Repositories</code>.<br>Okay… but what about the <code>switchToLatest</code> operator?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-278"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-276">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-277'
	>
	Imagine that you’re typing in a textfield—typing is quite fast.<br>For each character you type, an API call will be made. If we did that we’d absolutely trash the server with all that traffic.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-281"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-279">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-280'
	>
	This is where <code>switchToLatest</code> operator comes in handy. It <em>automatically cancels</em> any previously sent events and continues on with the latest one! That way, we only take whatever text we have for the last character coming into the stream.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-284"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-282">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-283'
	>
	Making the operator is pretty straightforward:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-286"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">extension</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Publisher</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">func flatMapLatest</span><span class="token">&lt;</span><span class="token" style="color: #005cc5;">T</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Publisher</span><span class="token">&gt;</span><span class="token">(</span><span class="token">_ transform</span><span class="token">: </span><span class="token" style="color: #d73a49;">@escaping</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #005cc5;">Self</span><span class="token">.Output</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> T</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> </span><span class="token">AnyPublisher</span><span class="token">&lt;</span><span class="token">T.Output, T.Failure</span><span class="token">&gt;</span><span class="token"> </span><span class="token" style="color: #d73a49;">where</span><span class="token"> </span><span class="token">T.Failure </span><span class="token" style="color: #d73a49;">==</span><span class="token"> </span><span class="token" style="color: #005cc5;">Self</span><span class="token">.Failure</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">return</span><span class="token"> </span><span class="token">map(</span><span class="token">transform</span><span class="token">)</span><span class="token">.</span><span class="token">switchToLatest(</span><span class="token">)</span><span class="token">.</span><span class="token">eraseToAnyPublisher(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-289"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-287">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-288'
	>
	Let’s (de)bounce forward</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-292"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-290">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-291'
	>
	You might’ve also noticed the <code>debounce</code> operator.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-295"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-293">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-294'
	>
	Along with <code>debounce</code>, <code>throttle</code> is also one of the operators that saves lives when using <em>RxSwift</em>, so it’s only natural that it found its place in <em>Combine</em>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-298"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-296">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-297'
	>
	So what’s so magical about it? Putting it simply, it does not let any events in the stream pass the point where debounce is placed, as long as the time between each of those events is shorter than the provided time interval.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-301"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-299">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-300'
	>
	Huh… it doesn’t sound that simple?<br>Think of it as a valve that is automatically shut if a stream of liquid is bigger than what the pipe can support.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-304"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-302">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-303'
	>
	So in the case where a user types fast, any character that comes before the period of <code>0.3</code> seconds has elapsed, will end up being dropped.<br>Once the user stops typing or slows down, events will pass freely for further processing.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-307"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-305">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-306'
	>
	This makes it perfect for text inputs because it guards against unintentional DDOS attacks and potential wrath of your sysadmins.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-312"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-308">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-309'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-310'
	>
	Note: If you aren’t using Combine beta 2, you’ll end up having quite some trouble setting up debounce since the only supported scheduler in the first beta is the ImmediateScheduler, which is no good in this case.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-315"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-313">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-314'
	>
	Share your resources!</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-318"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-316">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-317'
	>
	Last, but definitely not the least important operator used is <code>share</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-321"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-319">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-320'
	>
	If <code>share</code> wasn’t used then each subscription would re-trigger an API call, or putting it simply, resources wouldn’t be <em>shared</em>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-324"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-322">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-323'
	>
	Using it means that the part of the stream before the operator will get reused across all of its subscriptions, instead of getting invoked again. This avoids triggering further API calls on any of our <code>maps</code>, <code>flatMaps</code>, <code>sinks</code>, etc.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-327"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-325">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-326'
	>
	Addressing the model updates</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-329"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">didChange </span><span class="token" style="color: #d73a49;">=</span><span class="token"> search
</span></span><span class="line"><span class="token">   .</span><span class="token" style="color: #005cc5;">map</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">_</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token"> </span><span class="token">(</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">   .</span><span class="token">receive(</span><span class="token">on:</span><span class="token"> DispatchQueue.</span><span class="token">main</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   .</span><span class="token">eraseToAnyPublisher(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-332"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-330">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-331'
	>
	Remember when I mentioned that we need to notify the view on view model value changes? We’re doing it here.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-335"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-333">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-334'
	>
	Once the search event arrives (i.e. the API call finished and the data has been decoded), we’ll notify the view.<br>Since we also don’t care about the type here, the event is mapped into <code>Void</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-338"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-336">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-337'
	>
	It is extremely important that any events <strong><em>sent towards the UI are on the Main thread</em></strong>. Failing to do so will result in undefined behaviour, glitches or a crash. Since we’re doing that using the <code>didChange</code> property, we need to move that stream to the main thread.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-341"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-339">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-340'
	>
	Thankfully, Apple provided a method to do that with <em>Combine</em> in beta 2. It’s done by simply calling the <code>receive(on:)</code> operator in the exact moment when you want to switch.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-344"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-342">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-343'
	>
	Do note that <em>any code that executes below that will run on the thread you’ve assigned it on</em>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-347"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-345">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-346'
	>
	Is it time to finally update our repositories?!</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-350"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-348">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-349'
	>
	Why yes, it is! And we can do that by using the <code>assign</code> operator.<br>If you’ve used <em>RxSwift</em> you already guessed that this is basically its <code>bind</code> counterpart.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-353"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-351">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-352'
	>
	I’ll also make use of Swift 5’s new <code>Result</code> type and its <code>.get()</code> convenience method. This enables unwrapping an enum’s associated value if it exists, without requiring any conditional checks or switch statements.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-356"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-354">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-355'
	>
	However, there’s caveat that it throws if there’s no value. Thankfully, <em>Combine</em> has our backs—we can simply use <code>tryMap</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-359"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-357">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-358'
	>
	Swift will raise a red light though, since all errors need to be handled before using <code>assign</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-364"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-360">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-361'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-362'
	>
	Note: If you’re using sink you’re not required to handle the error. Specifically, you’re able to handle that in a block which it provides.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-367"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-365">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-366'
	>
	To remedy that, we’ll need a <code>catch</code> operator.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-370"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-368">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-369'
	>
	It’s important to use <code>catch</code> when passing data to the UI or when you want to keep your stream alive and well. Unhandled errors will terminate the stream – remember, we can only get one subscription and one error event per stream.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-373"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-371">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-372'
	>
	The closure returns an error and expects a publisher back. That gives us the choice either to handle the error and return a new publisher that’ll keep the stream alive, or simply let the error through.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-376"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-374">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-375'
	>
	Since we don’t care about the error in case, returning existing repositories is fine.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-378"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">_cancellable </span><span class="token" style="color: #d73a49;">=</span><span class="token"> search
</span></span><span class="line"><span class="token">   .</span><span class="token">tryMap</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #d73a49;">try</span><span class="token"> </span><span class="token" style="color: #005cc5;">$0</span><span class="token">.</span><span class="token">get(</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">   .</span><span class="token">catch</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">_</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token"> Publishers.</span><span class="token">Just(</span><span class="token">repositories</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">   .</span><span class="token" style="color: #005cc5;">assign</span><span class="token">(</span><span class="token">to:</span><span class="token"> \.</span><span class="token">repositories</span><span class="token">, </span><span class="token">on:</span><span class="token"> </span><span class="token" style="color: #005cc5;">self</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-381"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-379">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-380'
	>
	Main difference compared to <em>RxSwift</em> is that the returned value from <code>assign</code> needs to be stored into <code>_cancellable</code> instead of being stored into a <code>DisposeBag</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-384"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-382">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-383'
	>
	Overall usage is exactly the same, the only caveat being that we need to think about it ourselves during deinit and call cancel.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-387"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-385">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-386'
	>
	On the other hand, the default behaviour of <code>DisposeBag</code> can also be achieved.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-390"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-388">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-389'
	>
	If you want to do that, the returned stream needs to be wrapped into <code>AnyCancellable</code>, which requires a closure upon <code>init</code>. That closure is called upon deinit of the class that’s holding the <code>AnyCancellable</code> object.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-393"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-391">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-392'
	>
	In any case, depending on the approach, just be wary to call cancel if needed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-396"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-394">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-395'
	>
	And another thing—if you’re wondering, you can do this by using an approach similar to the <code>.subscribe(onNext:)</code> available in <em>RxSwift</em>. Talking <em>Combine</em> though, you’ll want to use the <code>sink</code> operator:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-398"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">_cancellable </span><span class="token" style="color: #d73a49;">=</span><span class="token"> search
</span></span><span class="line"><span class="token">   .</span><span class="token">sink(</span><span class="token">receiveValue:</span><span class="token"> </span><span class="token">{</span><span class="token"> [</span><span class="token" style="color: #d73a49;">unowned</span><span class="token"> </span><span class="token" style="color: #005cc5;">self</span><span class="token">] result </span><span class="token" style="color: #d73a49;">in</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">switch</span><span class="token"> result </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">case</span><span class="token"> .</span><span class="token">success(</span><span class="token" style="color: #d73a49;">let</span><span class="token"> repositories</span><span class="token">)</span><span class="token" style="color: #d73a49;">:</span><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #005cc5;">self</span><span class="token">.</span><span class="token">repositories</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> repositories
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">case</span><span class="token"> .</span><span class="token">failure(</span><span class="token" style="color: #d73a49;">let</span><span class="token"> error</span><span class="token">)</span><span class="token" style="color: #d73a49;">:</span><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #005cc5;">print</span><span class="token">(</span><span class="token">error</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-401"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-399">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-400'
	>
	And that’s it! Take a deep, relaxing breath if you’ve made it this far, we’re on the home stretch now.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-404"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-402">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-403'
	>
	What’s left to do is to cover the <code>_getRepositories(using:existingRepositories:)</code> method that you might have noticed all the way up there. That’s the method that’s making the API call and getting the data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-406"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token" style="color: #d73a49;">static</span><span class="token"> </span><span class="token">func _getRepositories</span><span class="token">(</span><span class="token">using query</span><span class="token">: </span><span class="token" style="color: #005cc5;">String</span><span class="token">, </span><span class="token">existingRepositories</span><span class="token">: </span><span class="token">[</span><span class="token">Repository</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> []</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> </span><span class="token">AnyPublisher</span><span class="token">&lt;</span><span class="token">Result</span><span class="token">&lt;</span><span class="token">[</span><span class="token">Repository</span><span class="token">]</span><span class="token">, </span><span class="token" style="color: #005cc5;">Error</span><span class="token">&gt;</span><span class="token">, </span><span class="token" style="color: #005cc5;">Never</span><span class="token">&gt;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">guard</span><span class="token"> </span><span class="token" style="color: #d73a49;">let</span><span class="token"> request </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">_makeRequest(</span><span class="token">using:</span><span class="token"> query</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">else</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #d73a49;">return</span><span class="token"> Publishers.</span><span class="token">Empty(</span><span class="token">)</span><span class="token">.</span><span class="token">eraseToAnyPublisher(</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">let</span><span class="token"> decoder </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">JSONDecoder(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   decoder.</span><span class="token">keyDecodingStrategy</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> .</span><span class="token">convertFromSnakeCase</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">return</span><span class="token"> URLSession.</span><span class="token">shared</span><span class="token">
</span></span><span class="line"><span class="token">       .</span><span class="token">dataTaskPublisher(</span><span class="token">for:</span><span class="token"> request</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">       .</span><span class="token" style="color: #005cc5;">map</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">$0</span><span class="token">.</span><span class="token">data</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">       .</span><span class="token" style="color: #005cc5;">decode</span><span class="token">(</span><span class="token">type:</span><span class="token"> Response</span><span class="token" style="color: #d73a49;">&lt;</span><span class="token">Repository</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token">.</span><span class="token" style="color: #d73a49;">self</span><span class="token">, </span><span class="token">decoder:</span><span class="token"> decoder</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">       .</span><span class="token" style="color: #005cc5;">map</span><span class="token"> </span><span class="token">{</span><span class="token"> .</span><span class="token">success(</span><span class="token" style="color: #005cc5;">$0</span><span class="token">.</span><span class="token">items</span><span class="token">.</span><span class="token" style="color: #005cc5;">sorted</span><span class="token">(</span><span class="token">by:</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">$0</span><span class="token">.</span><span class="token">stargazersCount</span><span class="token"> </span><span class="token" style="color: #d73a49;">&gt;</span><span class="token"> </span><span class="token" style="color: #005cc5;">$1</span><span class="token">.</span><span class="token">stargazersCount</span><span class="token"> </span><span class="token">}</span><span class="token">)</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">       .</span><span class="token">catch</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">_</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token"> Publishers.</span><span class="token">Just(</span><span class="token">.</span><span class="token">success(</span><span class="token">existingRepositories</span><span class="token">)</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">       .</span><span class="token">eraseToAnyPublisher(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-409"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-407">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-408'
	>
	Simple networking stuff.<br>Creating an <code>URLRequest</code> and an appropriate <code>JSONDecoder</code>, which is then used after the <code>dataTaskPublisher</code> retrieves the data needed for decoding.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-412"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-410">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-411'
	>
	Speaking of decoding, a really great addition is the <code>decode</code> operator. It enables decoding on the fly, <em>directly</em> on the stream by simply passing in the decoder. This avoids us having to write all of the boilerplate decoding logic, which is always nice.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-415"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-413">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-414'
	>
	Be mindful though, since decoding can also <code>throw</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-418"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-416">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-417'
	>
	Lastly, the publisher is type erased so that we lose all those wrapping publisher types (the same thing already seen with SwiftUI) and simply return an <code>AnyPublisher&lt;Result&gt;</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-421"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-419">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-420'
	>
	In case that it’s needed, I’m also attaching the <code>URLRequest</code> creation part:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-423"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token" style="color: #d73a49;">static</span><span class="token"> </span><span class="token">func _makeRequest</span><span class="token">(</span><span class="token">using query</span><span class="token">: </span><span class="token" style="color: #005cc5;">String</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> </span><span class="token">URLRequest</span><span class="token" style="color: #d73a49;">?</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">guard</span><span class="token"> </span><span class="token" style="color: #d73a49;">var</span><span class="token"> components </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">URLComponents(</span><span class="token">string:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">https://api.github.com/search/repositories</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">else</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #d73a49;">return</span><span class="token"> </span><span class="token" style="color: #005cc5;">nil</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">   components.</span><span class="token">queryItems</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> [</span><span class="token">URLQueryItem(</span><span class="token">name:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">q</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">, </span><span class="token">value:</span><span class="token"> query</span><span class="token">)</span><span class="token">]
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">guard</span><span class="token"> </span><span class="token" style="color: #d73a49;">let</span><span class="token"> url </span><span class="token" style="color: #d73a49;">=</span><span class="token"> components.</span><span class="token" style="color: #005cc5;">url</span><span class="token"> </span><span class="token" style="color: #d73a49;">else</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #d73a49;">return</span><span class="token"> </span><span class="token" style="color: #005cc5;">nil</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">var</span><span class="token"> request </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">URLRequest(</span><span class="token">url:</span><span class="token"> url</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">   request.</span><span class="token">addValue(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">application/json</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">, </span><span class="token">forHTTPHeaderField:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Content-Type</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">return</span><span class="token"> request
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-426"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-424">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-425'
	>
	And that’s all folks</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-429"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-427">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-428'
	>
	With this in place, we’re done! Searching now works and repositories are listed and sorted depending on their stargazers count.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-432"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-430">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-431'
	>
	I’m excited to see how we’ll be able to improve the code with further updates. Beta 2 has already provided some <em>Foundation</em> awesomeness which made things quite a bit easier.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-435"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-433">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-434'
	>
	Compared to the initial beta, we’ve gotten the <code>dataTaskPublisher</code> on the <code>URLSession</code> which we’d otherwise have to implement ourselves.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-438"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-436">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-437'
	>
	Most importantly, we’ve gotten other schedulers outside of the initially supplied <code>ImmediateScheduler</code> which wasn’t something we could use. That opened up the possibility to use <code>debounce</code> to throttle the events!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-441"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-439">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-440'
	>
	Next time, we’ll be making a details view that’ll show us some basic information about the repository and its author.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-444"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-442">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-443'
	>
	Stay tuned!</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/combine-makes-swiftui-shine/">Combine’s What Makes SwiftUI Really Shine</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>