Extension
allows us to addfunctionality
to existingtype
orprotocol
or some part of the existingApple SDK
library or even components inthird party package
that we use in theproject
.- However,
extension
inSwift
can be used with many more flexible and advanced ways than just using them to addproperty
ormethod
toexternal object
. In this article, we will study the same uses for them to be used in upcomingproject
.
1 / Add features to the existing Type:
- Starting simply have to use
extension
to add new, customAPI
for the formattype
components inApple system
such as theApple standard library
. Specific examples like we need to work on anapp
whose processinglogic
requires us toaccess
theelement
in different arrays, to avoid always having to check theindex
of theelement
that weaccess
. We can do the following:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">extension</span> <span class="token builtin">Array</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">element</span> <span class="token punctuation">(</span> at index <span class="token punctuation">:</span> <span class="token builtin">Int</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Element</span> <span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token keyword">guard</span> index <span class="token operator">>=</span> <span class="token number">0</span> <span class="token punctuation">,</span> index <span class="token operator"><</span> <span class="token builtin">count</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token keyword">self</span> <span class="token punctuation">[</span> index <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- Very simple but convenient, right? Now we can use the above
method
in anyArray
in theproject
. Not stopping there we can also make better customizations with the use ofextension
for theRandomAccessCollection
protocol
: RandomAccessCollection
defines the requests that thecollection
providesrandom access
to theelement
. Extending thisprotocol
we will use the newmethod
for anycollection
includingArray
:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">extension</span> <span class="token builtin">RandomAccessCollection</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">element</span> <span class="token punctuation">(</span> at index <span class="token punctuation">:</span> <span class="token builtin">Index</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Element</span> <span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token keyword">guard</span> <span class="token builtin">indices</span> <span class="token punctuation">.</span> <span class="token function">contains</span> <span class="token punctuation">(</span> index <span class="token punctuation">)</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token keyword">self</span> <span class="token punctuation">[</span> index <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- With only the above change, we can now use new
method
fortype
likeArray
,ArraySlice
,Range
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token comment">// Extracting an optional element from an Array</span> <span class="token keyword">guard</span> <span class="token keyword">let</span> fifthElement <span class="token operator">=</span> array <span class="token punctuation">.</span> <span class="token function">element</span> <span class="token punctuation">(</span> at <span class="token punctuation">:</span> <span class="token number">4</span> <span class="token punctuation">)</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token comment">// Doing the same thing, but using an ArraySlice instead:</span> <span class="token keyword">let</span> slice <span class="token operator">=</span> array <span class="token punctuation">[</span> <span class="token number">0</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token operator"><</span> <span class="token number">3</span> <span class="token punctuation">]</span> <span class="token keyword">guard</span> <span class="token keyword">let</span> secondElement <span class="token operator">=</span> slice <span class="token punctuation">.</span> <span class="token function">element</span> <span class="token punctuation">(</span> at <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token comment">// We could also use our new method with types like Range:</span> <span class="token keyword">guard</span> <span class="token keyword">let</span> thirdValue <span class="token operator">=</span> range <span class="token punctuation">.</span> <span class="token function">element</span> <span class="token punctuation">(</span> at <span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> |
- Using
extension
for theprotocol
gives us more flexibility in using themethod
andproperty
we add. - However, not all
extension
we add are aimed at the above general purpose. In some cases we need additionalconstraints
for specificextension
. - Let’s look at an example where they add
extension
to addmethod
help us calculate the total cost ofproducts
using thesame type constraints
to ensure themethod
will be called only when theSequence
conform
type of theProduct
value:
1 2 3 4 5 6 7 8 | <span class="token keyword">extension</span> <span class="token builtin">Sequence</span> <span class="token keyword">where</span> <span class="token builtin">Element</span> <span class="token operator">==</span> <span class="token builtin">Product</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">totalPrice</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Int</span> <span class="token punctuation">{</span> <span class="token function">reduce</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> price <span class="token punctuation">,</span> product <span class="token keyword">in</span> price <span class="token operator">+</span> product <span class="token punctuation">.</span> price <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- The useful thing of this
constraints
is that it not only references and guarantees the type for the protocol, but also can be used in theclosure
as follows:
1 2 3 4 5 6 7 8 | <span class="token keyword">extension</span> <span class="token builtin">Sequence</span> <span class="token keyword">where</span> <span class="token builtin">Element</span> <span class="token operator">==</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Void</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">callAll</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> forEach <span class="token punctuation">{</span> closure <span class="token keyword">in</span> <span class="token function">closure</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- In Swift 5.3, this feature was further upgraded so that we may use this
constraints
to personalize themethod
declaration for the types used to encapsulate it.
1 2 3 4 5 6 7 8 | <span class="token keyword">extension</span> <span class="token builtin">Sequence</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> callAll <span class="token operator"><</span> T <span class="token operator">></span> <span class="token punctuation">(</span> with input <span class="token punctuation">:</span> T <span class="token punctuation">)</span> <span class="token keyword">where</span> <span class="token builtin">Element</span> <span class="token operator">==</span> <span class="token punctuation">(</span> T <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Void</span> <span class="token punctuation">{</span> forEach <span class="token punctuation">{</span> closure <span class="token keyword">in</span> <span class="token function">closure</span> <span class="token punctuation">(</span> input <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Method
on may become useful when we want to pass thesame value
for theclosure
such as in the example of theorder
willnotify
allobserver
ofObservable
type withvalue
changes:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">class</span> <span class="token class-name">Observable</span> <span class="token operator"><</span> <span class="token builtin">Value</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">var</span> value <span class="token punctuation">:</span> <span class="token builtin">Value</span> <span class="token punctuation">{</span> <span class="token keyword">didSet</span> <span class="token punctuation">{</span> observations <span class="token punctuation">.</span> <span class="token function">callAll</span> <span class="token punctuation">(</span> with <span class="token punctuation">:</span> value <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">var</span> observations <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">(</span> <span class="token builtin">Value</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Void</span> <span class="token punctuation">]</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> |
2 / Reorganize APIs and Protocol Compliance:
Extension
often used in organizing code inproject
, this is a feature that we have done a lot onObjective-C
. We use this to groupAPI
with the same functionality that it provides to make it easier to find and rate the functionality.- In
Swift
we use the same approach to sort theAPI
byaccess level
. For example,Publish
, we have an constructor tobuild
eachwebsite
in which theSection
serves as a type so that the grouped groups must comply withpublic
,internal
, andprivate
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <span class="token keyword">public</span> <span class="token keyword">struct</span> <span class="token builtin">Section</span> <span class="token operator"><</span> <span class="token builtin">Site</span> <span class="token punctuation">:</span> <span class="token builtin">Website</span> <span class="token operator">></span> <span class="token punctuation">:</span> <span class="token builtin">Location</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">let</span> id <span class="token punctuation">:</span> <span class="token builtin">Site</span> <span class="token punctuation">.</span> <span class="token builtin">SectionID</span> <span class="token keyword">public</span> <span class="token keyword">private</span> <span class="token punctuation">(</span> <span class="token keyword">set</span> <span class="token punctuation">)</span> <span class="token keyword">var</span> items <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token builtin">Item</span> <span class="token operator"><</span> <span class="token builtin">Site</span> <span class="token operator">></span> <span class="token punctuation">]</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">extension</span> <span class="token builtin">Section</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">item</span> <span class="token punctuation">(</span> at path <span class="token punctuation">:</span> <span class="token builtin">Path</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Item</span> <span class="token operator"><</span> <span class="token builtin">Site</span> <span class="token operator">></span> <span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">items</span> <span class="token punctuation">(</span> taggedWith tag <span class="token punctuation">:</span> <span class="token builtin">Tag</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token punctuation">[</span> <span class="token builtin">Item</span> <span class="token operator"><</span> <span class="token builtin">Site</span> <span class="token operator">></span> <span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token keyword">internal</span> <span class="token keyword">extension</span> <span class="token builtin">Section</span> <span class="token punctuation">{</span> <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function">addItem</span> <span class="token punctuation">(</span> <span class="token number">_</span> item <span class="token punctuation">:</span> <span class="token builtin">Item</span> <span class="token operator"><</span> <span class="token builtin">Site</span> <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">Section</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token keyword">mutating</span> <span class="token keyword">func</span> <span class="token function">rebuildIndexes</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- In addition to the benefits of organizing the
code
, we do not have to give themethod
access level
but eachAPI
will automatically be provided with the necessary access. - The above implementation is completely applicable to the
protocol
, we can attach the right conditions for eachextension
we add, for example we createListViewController
conform
UITableViewDelegate
viaextension
:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">extension</span> <span class="token builtin">ListViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UITableViewDelegate</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">tableView</span> <span class="token punctuation">(</span> <span class="token number">_</span> tableView <span class="token punctuation">:</span> <span class="token builtin">UITableView</span> <span class="token punctuation">,</span> didSelectRowAt indexPath <span class="token punctuation">:</span> <span class="token builtin">IndexPath</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> item <span class="token operator">=</span> items <span class="token punctuation">[</span> indexPath <span class="token punctuation">.</span> item <span class="token punctuation">]</span> <span class="token function">showDetailViewController</span> <span class="token punctuation">(</span> <span class="token keyword">for</span> <span class="token punctuation">:</span> item <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> |
- Here we simply create
wrapper type
conditions toconform
Equatable
toprotocol
likeEquatable
andHashable
only if theWrapped
also satisfies the type of theprotocol
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token comment">// The compiler can still automatically generate the code required</span> <span class="token comment">// to conform to protocols like Equatable and Hashable even when</span> <span class="token comment">// adding those conformances through extensions:</span> <span class="token keyword">extension</span> <span class="token builtin">NetworkResponse</span> <span class="token punctuation">:</span> <span class="token builtin">Equatable</span> <span class="token keyword">where</span> <span class="token builtin">Wrapped</span> <span class="token punctuation">:</span> <span class="token builtin">Equatable</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token keyword">extension</span> <span class="token builtin">NetworkResponse</span> <span class="token punctuation">:</span> <span class="token builtin">Hashable</span> <span class="token keyword">where</span> <span class="token builtin">Wrapped</span> <span class="token punctuation">:</span> <span class="token builtin">Hashable</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token comment">// Most protocols will probably require us to write some form of</span> <span class="token comment">// bridging code ourselves, though. For example, here we make our</span> <span class="token comment">// network response use its wrapped type's description when it's</span> <span class="token comment">// being converted into a string, rather than defining its own:</span> <span class="token keyword">extension</span> <span class="token builtin">NetworkResponse</span> <span class="token punctuation">:</span> <span class="token builtin">CustomStringConvertible</span> <span class="token keyword">where</span> <span class="token builtin">Wrapped</span> <span class="token punctuation">:</span> <span class="token builtin">CustomStringConvertible</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> description <span class="token punctuation">:</span> <span class="token builtin">String</span> <span class="token punctuation">{</span> result <span class="token punctuation">.</span> description <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
3 / Specialize in the use of generics:
- At the last point, let’s take a look at how
extension
can be used to specialize generaltype
andprotocol
for each real-world use case: - Like the
Sequence
andRandomAccessCollection
protocol
that we have extended for ease of use like someApple Framework
often usegeneric
to makeAPI
more secure and extensible. InCombine
thepublisher
areimplement
to use thePublisher
protocol
that includesgeneric
types defined forOutput
orFailure
be generated when thePublisher
emits. - Those
generic
types allow us to fully implementCombine
operator
like usingResult
for thevalue
returned from thepublisher emit
:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">extension</span> <span class="token builtin">Publisher</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">asResult</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">AnyPublisher</span> <span class="token operator"><</span> <span class="token builtin">Result</span> <span class="token operator"><</span> <span class="token builtin">Output</span> <span class="token punctuation">,</span> <span class="token builtin">Failure</span> <span class="token operator">></span> <span class="token punctuation">,</span> <span class="token builtin">Never</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token builtin">Result</span> <span class="token punctuation">.</span> success <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token keyword">catch</span> <span class="token punctuation">{</span> error <span class="token keyword">in</span> <span class="token function">Just</span> <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token function">failure</span> <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">.</span> <span class="token function">eraseToAnyPublisher</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Extension
on specifies whether we deployCombine
resembleAsyncValue
withOutput
beassign
directly toResult
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">class</span> <span class="token class-name">AsyncValue</span> <span class="token operator"><</span> <span class="token builtin">Value</span> <span class="token punctuation">:</span> <span class="token builtin">Decodable</span> <span class="token operator">></span> <span class="token punctuation">:</span> <span class="token builtin">ObservableObject</span> <span class="token punctuation">{</span> @ <span class="token builtin">Published</span> <span class="token keyword">private</span> <span class="token punctuation">(</span> <span class="token keyword">set</span> <span class="token punctuation">)</span> <span class="token keyword">var</span> result <span class="token punctuation">:</span> <span class="token builtin">Result</span> <span class="token operator"><</span> <span class="token builtin">Value</span> <span class="token punctuation">,</span> <span class="token builtin">Error</span> <span class="token operator">></span> <span class="token operator">?</span> <span class="token keyword">private</span> <span class="token keyword">var</span> cancellable <span class="token punctuation">:</span> <span class="token builtin">AnyCancellable</span> <span class="token operator">?</span> <span class="token keyword">func</span> <span class="token function">load</span> <span class="token punctuation">(</span> from url <span class="token punctuation">:</span> <span class="token constant">URL</span> <span class="token punctuation">,</span> using session <span class="token punctuation">:</span> <span class="token builtin">URLSession</span> <span class="token operator">=</span> <span class="token punctuation">.</span> shared <span class="token punctuation">,</span> decoder <span class="token punctuation">:</span> <span class="token builtin">JSONDecoder</span> <span class="token operator">=</span> <span class="token punctuation">.</span> <span class="token keyword">init</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> cancellable <span class="token operator">=</span> session <span class="token punctuation">.</span> <span class="token function">dataTaskPublisher</span> <span class="token punctuation">(</span> <span class="token keyword">for</span> <span class="token punctuation">:</span> url <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token punctuation">.</span> data <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">decode</span> <span class="token punctuation">(</span> type <span class="token punctuation">:</span> <span class="token builtin">Value</span> <span class="token punctuation">.</span> <span class="token keyword">self</span> <span class="token punctuation">,</span> decoder <span class="token punctuation">:</span> decoder <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">asResult</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> sink <span class="token punctuation">{</span> <span class="token punctuation">[</span> <span class="token keyword">weak</span> <span class="token keyword">self</span> <span class="token punctuation">]</span> result <span class="token keyword">in</span> <span class="token keyword">self</span> <span class="token operator">?</span> <span class="token punctuation">.</span> result <span class="token operator">=</span> result <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- This approach with
constraints
allows us to take advantage ofSwift
‘s powerful network type inference capabilities, as well as the waySwiftUI
uses APIs to build display views. - For example, when we work on
IconView
are rendered with predefinedicon
. To facilitate the creation of aButton
including anicon
we can add anextension
that usestype constraints
Label
to define thecontent
which theButton
is to berender
:
1 2 3 4 5 6 7 8 | <span class="token keyword">extension</span> <span class="token builtin">Button</span> <span class="token keyword">where</span> <span class="token builtin">Label</span> <span class="token operator">==</span> <span class="token builtin">IconView</span> <span class="token punctuation">{</span> <span class="token keyword">init</span> <span class="token punctuation">(</span> icon <span class="token punctuation">:</span> <span class="token builtin">Icon</span> <span class="token punctuation">,</span> action <span class="token punctuation">:</span> @escaping <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Void</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> <span class="token keyword">init</span> <span class="token punctuation">(</span> action <span class="token punctuation">:</span> action <span class="token punctuation">,</span> label <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token function">IconView</span> <span class="token punctuation">(</span> icon <span class="token punctuation">:</span> icon <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- And now when we use the above
API
to createButton
instance
,complier
will automatically add a message telling us that we want to useIconView
as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">struct</span> <span class="token builtin">ProductView</span> <span class="token punctuation">:</span> <span class="token builtin">View</span> <span class="token punctuation">{</span> @ <span class="token builtin">ObservedObject</span> <span class="token keyword">var</span> viewModel <span class="token punctuation">:</span> <span class="token builtin">ProductViewModel</span> <span class="token keyword">var</span> body <span class="token punctuation">:</span> some <span class="token builtin">View</span> <span class="token punctuation">{</span> <span class="token builtin">VStack</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token function">Button</span> <span class="token punctuation">(</span> icon <span class="token punctuation">:</span> <span class="token punctuation">.</span> shoppingCart <span class="token punctuation">)</span> <span class="token punctuation">{</span> viewModel <span class="token punctuation">.</span> <span class="token function">performPurchase</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |