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

<channel>
	<title>swift combine &#8211; swiftyplace</title>
	<atom:link href="https://www.swiftyplace.com/blog/tag/swift-combine/feed" rel="self" type="application/rss+xml" />
	<link>https://www.swiftyplace.com</link>
	<description>Learn how to build amazing apps with SwiftUI and Combine</description>
	<lastBuildDate>Fri, 15 Sep 2023 08:56:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.2</generator>

<image>
	<url>https://www.swiftyplace.com/wp-content/uploads/2023/08/cropped-logo-1-32x32.png</url>
	<title>swift combine &#8211; swiftyplace</title>
	<link>https://www.swiftyplace.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to learn Functional Reactive Programming with the Combine Framework</title>
		<link>https://www.swiftyplace.com/blog/how-to-learn-combine-framework?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-learn-combine-framework</link>
					<comments>https://www.swiftyplace.com/blog/how-to-learn-combine-framework#respond</comments>
		
		<dc:creator><![CDATA[Karin Prater]]></dc:creator>
		<pubDate>Wed, 12 May 2021 11:50:42 +0000</pubDate>
				<category><![CDATA[Combine Framework]]></category>
		<category><![CDATA[combine framework]]></category>
		<category><![CDATA[combine resources]]></category>
		<category><![CDATA[how to learn combine]]></category>
		<category><![CDATA[swift combine]]></category>
		<guid isPermaLink="false">https://swiftyplace.com/?p=1492</guid>

					<description><![CDATA[<p>How to learn Combine? The best books, courses, tutorials, and blog posts. Find coding examples for SwiftUI and UIKit with networking.</p>
<p>The post <a rel="nofollow" href="https://www.swiftyplace.com/blog/how-to-learn-combine-framework">How to learn Functional Reactive Programming with the Combine Framework</a> appeared first on <a rel="nofollow" href="https://www.swiftyplace.com">swiftyplace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>So you are here because you want to learn Apple&#8217;s new framework Combine, but you are not sure how to start? &#8211; I am going to share with you the best resources that I used to learn Combine and some that I wish I found earlier. I have 3 different categories: books, courses, and free video/ tutorials, so you can take your pick.</p>
<p>Side Note: I know Combine is introduced in June 2019, so it technically cannot be called new anymore. However, the lack of material and documentation from Apple keeps this impression up, at least for me.</p>
<style>/*! elementor - v3.15.0 - 09-08-2023 */<br />
.elementor-column .elementor-spacer-inner{height:var(--spacer-size)}.e-con{--container-widget-width:100%}.e-con-inner>.elementor-widget-spacer,.e-con>.elementor-widget-spacer{width:var(--container-widget-width,var(--spacer-size));--align-self:var(--container-widget-align-self,initial);--flex-shrink:0}.e-con-inner>.elementor-widget-spacer>.elementor-widget-container,.e-con-inner>.elementor-widget-spacer>.elementor-widget-container>.elementor-spacer,.e-con>.elementor-widget-spacer>.elementor-widget-container,.e-con>.elementor-widget-spacer>.elementor-widget-container>.elementor-spacer{height:100%}.e-con-inner>.elementor-widget-spacer>.elementor-widget-container>.elementor-spacer>.elementor-spacer-inner,.e-con>.elementor-widget-spacer>.elementor-widget-container>.elementor-spacer>.elementor-spacer-inner{height:var(--container-widget-height,var(--spacer-size))}</style>
<style>/*! elementor - v3.15.0 - 09-08-2023 */<br />
.elementor-heading-title{padding:0;margin:0;line-height:1}.elementor-widget-heading .elementor-heading-title[class*=elementor-size-]>a{color:inherit;font-size:inherit;line-height:inherit}.elementor-widget-heading .elementor-heading-title.elementor-size-small{font-size:15px}.elementor-widget-heading .elementor-heading-title.elementor-size-medium{font-size:19px}.elementor-widget-heading .elementor-heading-title.elementor-size-large{font-size:29px}.elementor-widget-heading .elementor-heading-title.elementor-size-xl{font-size:39px}.elementor-widget-heading .elementor-heading-title.elementor-size-xxl{font-size:59px}</style>
<h2>Great tutorials and blog posts to start with Combine</h2>
<ul>
<li><a href="https://www.vadimbulavin.com/tag/combine/" target="_blank" rel="noopener">https://www.vadimbulavin.com/tag/combine/</a></li>
</ul>
<ul>
<li> <a href="https://theswiftdev.com/the-ultimate-combine-framework-tutorial-in-swift/" target="_blank" rel="noopener">https://theswiftdev.com/the-ultimate-combine-framework-tutorial-in-swift/</a></li>
<li><a href="https://medium.com/flawless-app-stories/problem-solving-with-combine-swift-4751885fda77" target="_blank" rel="noopener">https://medium.com/flawless-app-stories/problem-solving-with-combine-swift-4751885fda77</a></li>
<li><a href="https://scotteg.github.io" target="_blank" rel="noopener">https://scotteg.github.io</a></li>
<li>MVVM with Combine Tutorial for iOS at <a href=" https://www.raywenderlich.com/4161005-mvvm-with-combine-tutorial-for-ios">raywenderlich.com</a></li>
</ul>
<ul>
<li>Getting Started with Combine &#8211; Shai Mishali &#8211; App Builders 2020 on <a href="https://youtu.be/R7KgBgvQJ0c" target="_blank" rel="noopener">Youtube</a></li>
<li>Combine schedulers for testing <a href="https://github.com/pointfreeco/combine-schedulers" target="_blank" rel="noopener">here</a></li>
<li><a href="https://www.swiftbysundell.com/articles/" target="_blank" rel="noopener">https://www.swiftbysundell.com/articles/</a></li>
</ul>
<h2> Courses to learn Combine for iOS and SwiftUI</h2>
<h3>The Swifty Combine Course 23h <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b50.png" alt="⭐" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b50.png" alt="⭐" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b50.png" alt="⭐" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<p>at <a href="https://swiftyplace.newzenler.com/courses/master-combine-framework" target="_blank" rel="noopener">SwiftyPlace</a> $99</p>
<ul>
<li>this is my own course, so I am obviously recommending it.</li>
<li>the course covers all the fundaments for functional reactive programming</li>
<li>3 great demo projects</li>
<li>all examples in UIKit and Swifty</li>
<li>advanced topics: <strong>error handling, networking with URLSession, unit tests and dependency injection, and profiling with Timelane in Instruments</strong></li>
<li>special for UIKit: <strong>architecture pattern with MVVM, Coordinator pattern</strong> and Combine data streams</li>
<li>special for SwiftUI: <strong>MVVM and data flow </strong>with property wrappers and Combine</li>
<li>at the end of this course, you will have an advanced knowledge of Combine and can write complex applications with Combine</li>
</ul>
<h3>A Crash Course in Combine</h3>
<p>at <a href="https://www.pointfree.co/blog/posts/32-a-crash-course-in-combine" target="_blank" rel="noopener">Point Free</a></p>
<ul>
<li>Basic introduction to Combine</li>
<li>They show how to use Combine for the Composable Architecture</li>
<li>They also have a mini-course about SwiftUI and State Management</li>
<li>The platform uses a subscription model</li>
</ul>
<h2>Books for the Combine framework</h2>
<h3>Combine: Asynchronous Programming with Swift</h3>
<p>for $59  at <a href="https://www.raywenderlich.com/books/combine-asynchronous-programming-with-swift/v2.0" target="_blank" rel="noopener">raywenderlich.com</a></p>
<ul>
<li>This is a very good book to understand the basics.</li>
<li>Beginner friendly, especially if you just start with functional reactive programming</li>
<li>Some of the code is outdated.</li>
<li>There are not a lot of examples for SwiftUI.</li>
<li>The last larger project was not very useful to me. I had to put everything together. I wish I could have written more Combine code for it.</li>
</ul>
<h3>Practical Combine by Donny Wall</h3>
<p>for $29.99 <a href="https://practicalcombine.com/" target="_blank" rel="noopener">https://practicalcombine.com</a></p>
<ul>
<li>I found this a very good read. But it is not as complete as the Ray Wenderlich book.</li>
<li>If you are already familiar with reactive programming, you are going to enjoy this.</li>
<li>Lots of examples for networking</li>
<li>Up to date, with good resource recommendations.</li>
</ul>
<h3>Using Combine</h3>
<p>a great free online book <a href="https://heckj.github.io/swiftui-notes/" target="_blank" rel="noopener">github repo</a></p>
<ul>
<li>If you are already familiar with reactive programming, you are going to enjoy this.</li>
<li>It is a large collection of Combine code but not good for beginners.</li>
</ul>
<h3>Understanding Combine</h3>
<p>free online book <a href="https://www.apeth.com/UnderstandingCombine/start.html" target="_blank" rel="noopener">https://www.apeth.com/UnderstandingCombine/start.html</a></p>
<ul>
<li>a large collection with good examples</li>
</ul>
<h2>Fun stuff: interactive material to master Combine</h2>
<ul>
<li>iOS app to learn Combine operators <a href=" https://apps.apple.com/de/app/combine-operators/id1507756027?l=en">here</a> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f929.png" alt="🤩" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>
<li>Interactive diagrams for Rx Observers. You can learn about Operators with marble diagrams <a href="https://rxmarbles.com/#combineLatest" target="_blank" rel="noopener">here</a>.</li>
<li>Combine and RxSwift has a lot in common. You can find a RxSwift to Combine Cheatsheet <a href="https://github.com/CombineCommunity/rxswift-to-combine-cheatsheet" target="_blank" rel="noopener">here</a>.</li>
</ul>
<p>Let me know if I should add something to the list. I will gladly review it <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f913.png" alt="🤓" class="wp-smiley" style="height: 1em; max-height: 1em;" />.</p>
<p>The post <a rel="nofollow" href="https://www.swiftyplace.com/blog/how-to-learn-combine-framework">How to learn Functional Reactive Programming with the Combine Framework</a> appeared first on <a rel="nofollow" href="https://www.swiftyplace.com">swiftyplace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.swiftyplace.com/blog/how-to-learn-combine-framework/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to use Combine with MVVM for UIKit and SwiftUI &#8211; A practical example project with fetching tweet</title>
		<link>https://www.swiftyplace.com/blog/how-to-use-combine-with-mvvm-for-uikit-and-swiftui-a-practical-example-project-with-fetching-tweet?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-use-combine-with-mvvm-for-uikit-and-swiftui-a-practical-example-project-with-fetching-tweet</link>
					<comments>https://www.swiftyplace.com/blog/how-to-use-combine-with-mvvm-for-uikit-and-swiftui-a-practical-example-project-with-fetching-tweet#respond</comments>
		
		<dc:creator><![CDATA[Karin Prater]]></dc:creator>
		<pubDate>Wed, 12 May 2021 11:49:00 +0000</pubDate>
				<category><![CDATA[SwiftUI]]></category>
		<category><![CDATA[Combine Framework]]></category>
		<category><![CDATA[UIKit]]></category>
		<category><![CDATA[combine framework]]></category>
		<category><![CDATA[swift combine]]></category>
		<category><![CDATA[Swiftui combine]]></category>
		<category><![CDATA[UIKit combine]]></category>
		<guid isPermaLink="false">https://swiftyplace.com/?p=1487</guid>

					<description><![CDATA[<p>In this tutorial, I want to show you how to create data streams with Combine. You will see an example project that implements MVVM. A Twitter example.</p>
<p>The post <a rel="nofollow" href="https://www.swiftyplace.com/blog/how-to-use-combine-with-mvvm-for-uikit-and-swiftui-a-practical-example-project-with-fetching-tweet">How to use Combine with MVVM for UIKit and SwiftUI &#8211; A practical example project with fetching tweet</a> appeared first on <a rel="nofollow" href="https://www.swiftyplace.com">swiftyplace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Greetings, fellow developers! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f5a5.png" alt="🖥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> In this blog post, we&#8217;re about to embark on a technical journey that holds immense potential for your app architecture skills. Our focus? The seamless integration of Combine and MVVM—two pillars of modern application development. Our goal? To build a practical example project centered around fetching tweets, designed for both UIKit and SwiftUI environments. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f426.png" alt="🐦" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>In this tutorial, I want to show you how to create data streams with Combine. You will see an example project that implements MVVM. A Twitter example.</p>
<p>For those keen on expanding their knowledge further, <a href="https://www.swiftyplace.com/courses/master-combine-framework">The Swifty Combine Framework Course </a>offers an in-depth exploration of Combine and MVVM, ensuring you&#8217;re well-equipped to tackle real-world scenarios. So, if you&#8217;re ready to elevate your app architecture game, let&#8217;s delve into the technical realm of Combine with MVVM. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3d7.png" alt="🏗" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<style>/*! elementor - v3.15.0 - 09-08-2023 */<br />
.elementor-column .elementor-spacer-inner{height:var(--spacer-size)}.e-con{--container-widget-width:100%}.e-con-inner>.elementor-widget-spacer,.e-con>.elementor-widget-spacer{width:var(--container-widget-width,var(--spacer-size));--align-self:var(--container-widget-align-self,initial);--flex-shrink:0}.e-con-inner>.elementor-widget-spacer>.elementor-widget-container,.e-con-inner>.elementor-widget-spacer>.elementor-widget-container>.elementor-spacer,.e-con>.elementor-widget-spacer>.elementor-widget-container,.e-con>.elementor-widget-spacer>.elementor-widget-container>.elementor-spacer{height:100%}.e-con-inner>.elementor-widget-spacer>.elementor-widget-container>.elementor-spacer>.elementor-spacer-inner,.e-con>.elementor-widget-spacer>.elementor-widget-container>.elementor-spacer>.elementor-spacer-inner{height:var(--container-widget-height,var(--spacer-size))}</style>
<p>		https://youtu.be/O8vY5LUDagY</p>
<style>/*! elementor - v3.15.0 - 09-08-2023 */<br />
.elementor-heading-title{padding:0;margin:0;line-height:1}.elementor-widget-heading .elementor-heading-title[class*=elementor-size-]>a{color:inherit;font-size:inherit;line-height:inherit}.elementor-widget-heading .elementor-heading-title.elementor-size-small{font-size:15px}.elementor-widget-heading .elementor-heading-title.elementor-size-medium{font-size:19px}.elementor-widget-heading .elementor-heading-title.elementor-size-large{font-size:29px}.elementor-widget-heading .elementor-heading-title.elementor-size-xl{font-size:39px}.elementor-widget-heading .elementor-heading-title.elementor-size-xxl{font-size:59px}</style>
<h2>Project Set-up with STTwitter</h2>
<p>If you want to  use STTwitter, you can use CocoPods with:</p>
<pre data-line="">
				<code readonly="true">
					<xmp>pod 'STTwitter'
pod 'LBTATools'
pod 'SDWebImage'</xmp>
				</code>
</pre>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.</p>
<pre data-line="">
				<code readonly="true">
					<xmp>I am first going to show you how to fetch tweets with STTwitter (https://github.com/nst/STTwitter). Then we will build the view model and last I will show you how to connect the view model with UIKit and SwiftUI.
</xmp>
				</code>
</pre>
<style>/*! elementor - v3.15.0 - 09-08-2023 */<br />
.elementor-widget-image{text-align:center}.elementor-widget-image a{display:inline-block}.elementor-widget-image a img[src$=".svg"]{width:48px}.elementor-widget-image img{vertical-align:middle;display:inline-block}</style>
<p>												<img decoding="async" width="800" height="742" src="https://swiftyplace.com/wp-content/uploads/2023/08/final-app-demo.jpg" alt="" loading="lazy" srcset="https://swiftyplace.com/wp-content/uploads/2023/08/final-app-demo.jpg 913w, https://swiftyplace.com/wp-content/uploads/2023/08/final-app-demo-300x278.jpg 300w, https://swiftyplace.com/wp-content/uploads/2023/08/final-app-demo-768x712.jpg 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></p>
<h2>Model definition for Tweets</h2>
<p>We need two different model definitions for Tweet and User</p>
<pre data-line="">
				<code readonly="true">
					<xmp>import Foundation
struct Tweet: Codable {       
   let text: String        
   let user: User       
}
struct User: Codable {        
   let name, profileImageUrl: String
}
</xmp>
				</code>
</pre>
<p>We will use a different struct to store the secret and key for the Twitter API. You can request a secrete and key at <a href="https://apps.twitter.com/" target="_blank" rel="noopener">https://apps.twitter.com/</a>.</p>
<pre data-line="">
				<code readonly="true">
					<xmp>import Foundation
import STTwitter
import Combine 
struct TwitterAPI {        
   let key = "xxxxxxxxxxxxxx" // use your own key here    
   let key = "xxxxxxxxxxxxxx" // use your own secrete here    
   var api: STTwitterAPI        
   init() {        
      api = STTwitterAPI(appOnlyWithConsumerKey: key, consumerSecret: secret)    
   }    
   func verifyCredentials() -> Future<(String?, String?), Error> {              
       Future { promise in                        
           api.verifyCredentials(userSuccessBlock: { (username, userId) in                       
               promise(.success((username, userId)))                        
           }, errorBlock: { (err) in              
               promise(Result.failure(err!))                    
          })              
      }       
   }    
   func getSearchTweets(with query: String) -> AnyPublisher<[Tweet], Error> {        
      Future { promise in            
         api.getSearchTweets(withQuery: query, successBlock: { (data, res) in
               promise(.success(res))           
         }, errrBlock: { (err) in            
               promise(.failure(err!))            
         })
       }       
       .compactMap({ $0 })        
       .tryMap { try JSONSerialization.data(withJSONObject: $0,  options: .prettyPrinted)  }        
       .decode(type: [Tweet].self, decoder: jsonDecoder)        
       .eraseToAnyPublisher()    
  } 
   var jsonDecoder: JSONDecoder {        
      let decoder = JSONDecoder()        
      decoder.keyDecodingStrategy = .convertFromSnakeCase        
      return decoder    
   }
}</xmp>
				</code>
</pre>
<p>We want to use these 2 API calls with Combine.</p>
<pre data-line="">
				<code readonly="true">
					<xmp>api.getSearchTweets(withQuery: query, successBlock: { (data, res) in          
   //....
}, errorBlock: { (err) in        
   //....
} 
api.verifyCredentials(userSuccessBlock: { (username, userId) in        
   //.... 
}, errorBlock: { (err) in        
   //....
}</xmp>
				</code>
</pre>
<p>If you want to use ad-hoc callbacks with Combine, you can wrap them in Future publishers. This works if you only expect one-time callbacks. For callbacks or listeners that will be continuously called multiple times, it is better to define your own publisher.     This struct serves as the data provider.  You can extend this to use dependency injection.</p>
<h2>View Model with CurrentValueSubject or @Published</h2>
<p>In the view model, we hold all data that is the array of tweets and the search text term. We will also use it to fetch the tweets. The Combine data streams are set-up in the initializer of the view model.</p>
<p>Here is the implementation for UIKit with CurrentValueSubject, whereas SwiftUI works best with @Published. Please note that @Published probably uses a CurrentValueSubject as a publisher which you can access with the $ sign.</p>
<pre data-line="">
				<code readonly="true">
					<xmp>import Foundation
import Combine 
class TwitterViewModel {    
   // SwiftUI implementation with @Published
   // @Published var tweets = [Tweet]()
   // @Published var searchText = "Paul Hudson"
   //UIKit implementation with CurrentValueSubject
   let tweets = CurrentValueSubject<[Tweet], Never>([Tweet]())
   let searchText = CurrentValueSubject<String, Never>("Paul Hudson")   
   let twitterAPI = TwitterAPI()    
   var subsciptions = Set<AnyCancellable>()        
   let isTwitterConnected = CurrentValueSubject<Bool, Never>(false)          
   let errorMessage = CurrentValueSubject<String?, Never>(nil)        
   init() {        
      twitterAPI.verifyCredentials()            
         .sink { [unowned self] (completion) in            
            switch completion {           
            case .failure(let error):                                
               self.errorMessage.send(error.localizedDescription)                           
            case .finished: return            
            }        
         } receiveValue: { [unowned self] (username, id) in                           
            print("success")            
            self.isTwitterConnected.send(true)            
            self.setupSearch()        
         }.store(in: &subsciptions)    
   }       
   func setupSearch() {    
      // $searchText     
      // with @Published         
      searchText
         .removeDuplicates()            
         .debounce(for: .milliseconds(500), scheduler: RunLoop.main)            
         .map { [unowned self] (searchText) -> AnyPublisher<[Tweet], Never> in
               self.twitterAPI.getTweets(with: searchText)                    
                  .catch { (error) in                       
                      Just([Tweet]())                    
                  }                    
                  .eraseToAnyPublisher()            
         }            
         .switchToLatest()            
         .sink { [unowned self] (tweets) in                         
            self.tweets.send(tweets)            
         }.store(in: &subsciptions)  
   }
}</xmp>
				</code>
</pre>
<h2>FlatMap, SwitchToLatest, and error handling with catch</h2>
<p>A data stream is set up from the searchText publisher that fetches tweets. Because we want to use the getSearchTweets function that returns an AnyPublisher with the tweets, we need to have a data stream inside a stream. You have 2 possibilities:</p>
<ul>
<li><strong><a href="https://developer.apple.com/documentation/combine/publishers/merge/flatmap(maxpublishers:_:)-2z9wm" target="_blank" rel="noopener">flatmap</a></strong>: executes mulitple data streams in parallel and publishes all values downstream</li>
<li><strong>map + <a href="https://developer.apple.com/documentation/combine/publishers/merge/switchtolatest()-l0p9" target="_blank" rel="noopener">switchToLatest</a></strong>: execute only the data stream that was initiated the latest</li>
</ul>
<p>For this example, we only want to show the tweets for the latest search request. All earlier search request are discarded. Therefor switchToLast is a good fit for our example.</p>
<p>In order to catch errors in a Combine data stream we can use the catch operator. The catch operator expects a replacement publisher, that will be used in place of an occuring error. In this example we use a Just publisher, that just publishes a value. We publish an empty array of tweets with  <strong>Just([Tweet]()). </strong>The tweets property is then also set to an empty array. If you don&#8217;t want to pass an actual value or just ignore the error, you can use an Empty publisher, which does not pass a value und only completes the stream.</p>
<pre data-line="">
				<code readonly="true">
					<xmp>    .catch { (error) in            
        //.  Just([Tweet]())            
        Empty(completeImmediately: true)    
    }</xmp>
				</code>
</pre>
<h2>Integrating with an UIKit project</h2>
<p>For UIKit the implementation is more work than for SwiftUI. First (1) we create a data stream from the UITextField (search field) to update the connected CurrentValueSubject search text in the view model. Every time the user types a new letter in the textbox a new value is passed to the CurrentValueSubject and passed in the data stream that fetches tweets. We create another data stream from the view model back to the UIViewController (2). When the tweet CurrentValueSubject has a new value, we call tableView.reloadData().</p>
<pre data-line="">
				<code readonly="true">
					<xmp>import UIKit
import SDWebImage //loading image url
import LBTATools //stack easy layout
import Combine
class ViewController: UITableViewController {        
   let twitterViewModel = TwitterViewModel()
   let searchController = UISearchController(searchResultsController: nil)    
   var subscriptions = Set<AnyCancellable>()     
   override func viewDidLoad() {        
      super.viewDidLoad()                
      setupSearchBarListeners()        
      navigationItem.searchController = searchController        
      navigationController?.navigationBar.prefersLargeTitles = true        
      navigationItem.title = "Search Tweets"        
      searchController.obscuresBackgroundDuringPresentation = false    
   }
    fileprivate func setupSearchBarListeners() {
       // 1. data stream form UITextField to bind property in view model
        let publisher = NotificationCenter.default
                    .publisher(for: UISearchTextField.textDidChangeNotification,
                            object: searchController.searchBar.searchTextField)
        publisher
            .compactMap {
                ($0.object as? UISearchTextField)?.text
            }
            .sink { [unowned self] (str) in
                self.twitterViewModel.searchText.send(str)
            }.store(in: &subscriptions)
        // 2. update UITableView whenever tweets are updated
        twitterViewModel.tweets.sink { [unowned self] (_) in
            self.tableView.reloadData()
        }.store(in: &subscriptions)
    }
   override func tableView(_ tableView: UITableView,
                    numberOfRowsInSection section: Int) -> Int {
            return twitterViewModel.tweets.value.count
   }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = TweetCell(style: .subtitle, reuseIdentifier: nil)
        let tweet = twitterViewModel.tweets.value[indexPath.row]
        cell.tweetTextLabel.text = tweet.text
        cell.nameLabel.text = tweet.user.name
        cell.profileImageView.sd_setImage(with: URL(string:tweet.user.profileImageUrl.replacingOccurrences(of: "http", with: "https")))
        return cell
    }
} </xmp>
				</code>
</pre>
<pre data-line="">
				<code readonly="true">
					<xmp>    class TweetCell: UITableViewCell {
        let nameLabel = UILabel(text: "Username",
                                                font: .boldSystemFont(ofSize: 16),
                                                textColor: .black)
        let tweetTextLabel = UILabel(text: "Tweet Text MultiLines",
                                                 font: .systemFont(ofSize: 16),
                                                textColor: .darkGray,
                                                numberOfLines: 0)
        let profileImageView = UIImageView(image: nil,
                                                          contentMode: .scaleAspectFill)
        override init(style: UITableViewCell.CellStyle,
                        reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            profileImageView.layer.cornerRadius = 8
            profileImageView.layer.borderWidth = 0.5
            hstack(
                profileImageView.withSize(.init(width: 50, height: 50)),
                stack(nameLabel, tweetTextLabel, spacing: 8),
                spacing: 20,
                alignment: .top
            ).withMargins(.allSides(24))
        }
        required init?(coder: NSCoder) {
            fatalError()
        }
    }</xmp>
				</code>
</pre>
<h2>Integrating with a SwiftUI project</h2>
<p>In SwiftUI we can use the binding between @Published properties in ObservableObject and views. For example, we can bind the search text to a text field.</p>
<pre data-line="">
				<code readonly="true">
					<xmp>import SwiftUI
struct ContentView: View {   
    @StateObject var tweetViewModel = TweetViewModel()       
    let grayColor = Color(hue: 0, saturation: 0, brightness: 0.9)   
    var body: some View {       
        VStack(alignment: .leading, spacing: 20) {                       
            Text("Search Tweets").font(.title)           
            HStack(spacing: 20) {               
                HStack {                   
                    Image(systemName: "magnifyingglass")
                           .foregroundColor(Color(.lightGray))                                   
                    TextField("Search", text: $tweetViewModel.searchText)               
                }.padding(5)               
                 .background(RoundedRectangle(cornerRadius: 5).fill(grayColor))               
               Button(action: {                   
                  tweetViewModel.searchText = ""               
                }, label: { Text("Cancel")  })           
            }    
            List(tweetViewModel.tweets, id: .self) { tweet  in              
                VStack(alignment: .leading) {               
                     Text(tweet.user.name).bold()               
                     Text(tweet.text).foregroundColor(.gray)           
                }
            }.animation(.easeInOut)                   
        }.padding()   
    }   
}</xmp>
				</code>
</pre>
<p>The post <a rel="nofollow" href="https://www.swiftyplace.com/blog/how-to-use-combine-with-mvvm-for-uikit-and-swiftui-a-practical-example-project-with-fetching-tweet">How to use Combine with MVVM for UIKit and SwiftUI &#8211; A practical example project with fetching tweet</a> appeared first on <a rel="nofollow" href="https://www.swiftyplace.com">swiftyplace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.swiftyplace.com/blog/how-to-use-combine-with-mvvm-for-uikit-and-swiftui-a-practical-example-project-with-fetching-tweet/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Start learning the Combine framework</title>
		<link>https://www.swiftyplace.com/blog/start-learning-the-combine-framework?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=start-learning-the-combine-framework</link>
					<comments>https://www.swiftyplace.com/blog/start-learning-the-combine-framework#respond</comments>
		
		<dc:creator><![CDATA[Karin Prater]]></dc:creator>
		<pubDate>Wed, 12 May 2021 11:47:24 +0000</pubDate>
				<category><![CDATA[Combine Framework]]></category>
		<category><![CDATA[combine framework]]></category>
		<category><![CDATA[swift combine]]></category>
		<guid isPermaLink="false">https://swiftyplace.com/?p=1484</guid>

					<description><![CDATA[<p>In this free course, you will learn the basics of the Combine framework. This is for absolute beginners in functional reactive programming and Combine</p>
<p>The post <a rel="nofollow" href="https://www.swiftyplace.com/blog/start-learning-the-combine-framework">Start learning the Combine framework</a> appeared first on <a rel="nofollow" href="https://www.swiftyplace.com">swiftyplace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In this course, you will learn the basics of the Combine framework. This is for absolute beginners in functional reactive programming and Combine <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f929.png" alt="🤩" class="wp-smiley" style="height: 1em; max-height: 1em;" />. You can get the full course on Combine <a href="https://www.swiftyplace.com/courses/master-combine-framework">here.</a></p>
<p>https://youtu.be/bxXpC5aENgY		</p>
<h2>Subscribers and Subscriptions<br />
</h2>
<p>First I will explain how adding a subscriber like sink or assign to a publisher creates a subscription. You will learn how to cancel a subscription that means how to stop a data stream from passing values. You will also learn that passing an error <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a3.png" alt="💣" class="wp-smiley" style="height: 1em; max-height: 1em;" /> will complete the data stream.</p>
<h2>Subscribers and Subscriptions<br />
Publishers and Subjects<br />
</h2>
<p>In the second section, you will learn about a special type of publisher that is Subjects. I will show you how to use CurrentValueSubjects and PassthroughSubjects. In SwiftUI you can also use a publisher with the property wrapper @Published. You will learn the difference between these 3 publishers and their specific use cases.</p>
<h2>Example projects for UIkit and SwiftUI<br />
</h2>
<p>We will also write 2 demo projects <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f44b.png" alt="👋" class="wp-smiley" style="height: 1em; max-height: 1em;" /> for UIKit and SwiftUI. The goal is to use Subjects and @Published to create data streams from user input. By the end of this course, you will be able to create simple data streams between different parts of your projects.</p>
<p>I am using MVVM to illustrate how easy it is to separate tasks into their own components. Combine is a great tool for loose communication between different components. Comparable to the Delegate pattern, closures, and observer pattern.</p>
<h2>Course overview:<br />
</h2>
<p>0:00 Intro</p>
<p>03:21 subscriptions</p>
<p>17:49 limited subscriptions</p>
<p>31:43 assign(to,on) Subscriber</p>
<p>40:56 assign(to,on) strong reference and memory cycle problems</p>
<p>46:55 assign(to) with @Published properties</p>
<p>52:55 multithreading with .receive(on) and subscribe(on)</p>
<p>01:01:36 subscription as the contract between publishers and subscribers</p>
<p>01:14:18 publishers</p>
<p>01:18:25 CurrentValueSubject</p>
<p>01:26:24 PassthroughSubject</p>
<p>01:39:42 @Published</p>
<p>01:49:25 Combine in SwiftUI</p>
<p>01:55:47 Demo project UIKit</p>
<p>02:12:13 Demo project SwiftUI</p>
<p>02:37:49 where to go from here</p>
<h3>Resources</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b07.png" alt="⬇" class="wp-smiley" style="height: 1em; max-height: 1em;" /> download playgrounds for the course <a href="https://school.swiftyplace.com/f/free-combine-course" target="_blank" rel="noopener">here</a> </p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4d3.png" alt="📓" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Resources to learn Combine <a href="https://www.swiftyplace.com/blog/how-to-learn-combine-framework">here</a></p>
<h2>How to go from here:<br />
</h2>
<ul>
<li> convenience Publishers: Just, Future, Result, Fail, Empty <a href="https://developer.apple.com/documentation/combine " target="_blank" rel="noopener">https://developer.apple.com/documentation/combine </a></li>
<li>Foundation: URLSession dataTask publisher, Notification center, KVO publisher</li>
<li>operators: map, tryMap, compactMap, scan, collect, append, decode <a href="https://developer.apple.com/documentation/combine/publishers-merge-publisher-operators " target="_blank" rel="noopener">https://developer.apple.com/documentation/combine/publishers-merge-publisher-operators </a></li>
<li>throwing errors: Fail publisher, Future with error</li>
<li>error handling operators: catch, tryCatch, replaceError(with), assertNoFailure , mapError, setFailureType(to)</li>
<li>multithreading: Schedular protocol, receive(on), subscribe(on), batch processing with flatMap, and set number of tasks executed in parallel with flatMap(maxPublisher)</li>
<li>control resources: dropFirst, debounce, throttle, filter, removeDupicates</li>
<li>unit testing: functions that return AnyPublisher, eraseToAnyPublisher, Result.publisher</li>
<li>communication design patterns can be replaced by Combine data streams: Delegate pattern, closures, and Observer patterns</li>
</ul>
<p>The post <a rel="nofollow" href="https://www.swiftyplace.com/blog/start-learning-the-combine-framework">Start learning the Combine framework</a> appeared first on <a rel="nofollow" href="https://www.swiftyplace.com">swiftyplace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.swiftyplace.com/blog/start-learning-the-combine-framework/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: www.swiftyplace.com @ 2026-07-21 23:41:42 by W3 Total Cache
-->