<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Bassem Qoulta on Medium]]></title>
        <description><![CDATA[Stories by Bassem Qoulta on Medium]]></description>
        <link>https://medium.com/@deda9?source=rss-43616b42e912------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*y4cQuuhA4ITOuv43p-Ir7A.jpeg</url>
            <title>Stories by Bassem Qoulta on Medium</title>
            <link>https://medium.com/@deda9?source=rss-43616b42e912------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 13:35:49 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@deda9/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Learn SwiftData with SwiftUI]]></title>
            <link>https://blog.devgenius.io/learn-swiftdata-with-swiftui-7d39d1b79f98?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/7d39d1b79f98</guid>
            <category><![CDATA[swiftdata]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[core-data]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Sun, 22 Oct 2023 22:05:56 GMT</pubDate>
            <atom:updated>2023-10-23T09:49:18.899Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Awn_SDa2_04Gxerd" /><figcaption>Photo by <a href="https://unsplash.com/@frostroomhead?utm_source=medium&amp;utm_medium=referral">Rodion Kutsaiev</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>I used to work as an Android Developer and I used to use SQLLite and I wouldn’t think that Apple would come up with SwiftData which is really powerful to save your data with really easy syntax and structure.</p><p>SwiftData enables you to add persistence to your app quickly, with minimal code and no external dependencies, you wont need to write CoreData complex code anymore. Using modern language features like macros, SwiftData enables you to write code that is fast, efficient, and safe, enabling you to describe the entire model layer for your app.</p><h3>Define the data model</h3><p>The first thing we will need to let SwiftData save instances of a model class, import the framework and annotate that class with the <a href="https://developer.apple.com/documentation/swiftdata/model()">Model()</a> macro. This macro updates the class with conformance to the <a href="https://developer.apple.com/documentation/swiftdata/persistentmodel">PersistentModel</a> protocol, which SwiftData uses to examine the class and generate an internal schema and enables change tracking for the class by adding conformance to the <a href="https://developer.apple.com/documentation/Observation/Observable">Observable</a> protocol.</p><p>Let’s say that we need to create <strong>Todo-list</strong> application where you can add your task and add your sub-tasks inside.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*ObXXEhf8i9CQNtBd67xI2Q.gif" /></figure><p>So the first think we will think of is to create Task <a href="https://developer.apple.com/documentation/swiftdata/model()">Model()</a> and SubTask <a href="https://developer.apple.com/documentation/swiftdata/model()">Model()</a> and the <a href="https://developer.apple.com/documentation/swiftdata/relationship(_:deleterule:minimummodelcount:maximummodelcount:originalname:inverse:hashmodifier:)">Relationship</a> between them.</p><pre>@Model<br>final class Task {<br>    @Attribute(.unique)<br>    let name: String<br>    <br>    @Relationship(deleteRule: .cascade, inverse: \SubTask.task)<br>    var subTasks: [SubTask] = []<br>    <br>    init(name: String) {<br>        self.name = name<br>    }<br>}</pre><pre>@Model<br>final class SubTask {<br>    let name: String<br>    var task: Task?<br>    <br>    init(name: String) {<br>        self.name = name<br>    }<br>}</pre><p>As we did use <em>@Model</em>, SwiftData will automatically convert Task()and SubTask to be savable which include all non-computed properties of a class as long as they use compatible types such as <a href="https://developer.apple.com/documentation/Swift/Bool">Bool</a>, <a href="https://developer.apple.com/documentation/Swift/Int">Int</a>, and <a href="https://developer.apple.com/documentation/Swift/String">String</a>, as well as complex value types such as structures, enumerations, and other value types that conform to the <a href="https://developer.apple.com/documentation/Swift/Codable">Codable</a> protocol.</p><h3>Customize the persistence behavior of model attributes</h3><pre>@Attribute(.unique)<br>let name: String</pre><p><a href="https://developer.apple.com/documentation/swiftdata/attribute(_:originalname:hashmodifier:)">Attribute(_:originalName:hashModifier:)</a> macro is a property of a model class that SwiftData uses to change the behavior of the model, so in our demo to make Task unique we did use @Attribute(.unique) but the framework’s default behavior for attributes is <strong><em>sufficient</em></strong>. However, if you need to alter how SwiftData handles the persistence of a particular attribute, use one of the provided schema macros.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*449MkAOtRkBXFudD9JxXCQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*15HOAboZSuQFfCR4LXdj3g.png" /></figure><h3>Defining the relationship between Task and SubTask</h3><pre>@Relationship(deleteRule: .cascade, inverse: \SubTask.task)<br>var subTasks: [SubTask] = []</pre><p>So as we can see that each Task can have many SubTask but each SubTask will be only inside one Task so the relationship will be <strong>one-to-many</strong>.</p><p>The class also applies the <a href="https://developer.apple.com/documentation/swiftdata/relationship(_:deleterule:minimummodelcount:maximummodelcount:originalname:inverse:hashmodifier:)">Relationship(_:deleteRule:minimumModelCount:maximumModelCount:originalName:inverse:hashModifier:)</a> macro to the <em>subTasks</em> property and the values of this macro to configure the relationship.</p><p>For example the deleteRule parameter specifies how SwiftData handles delete operations with regards to the related data. The <a href="https://developer.apple.com/documentation/swiftdata/schema/relationship/deleterule-swift.enum/cascade">Schema.Relationship.DeleteRule.cascade</a> delete rule tells SwiftData to delete all related data when deleting the primary object. For example, deleting an Task in the sample app causes SwiftData to also delete all <em>subTasks</em> contained in that Task.</p><p>The inverse parameter is a key path to define the relationship in one of the model types, So the value for inverse must point to a property of the type of the model like the store property subTasks which is declared in the related model class Task.</p><p>But if you don’t want to delete the <em>subTasks</em> within a <em>task</em>, you can use the <a href="https://developer.apple.com/documentation/swiftdata/schema/relationship/deleterule-swift.enum/nullify">Schema.Relationship.DeleteRule.nullify</a> delete rule. This rule tells SwiftData to set the task’s <em>subTasks</em> property to nil for each <em>subTask</em> contained in the task when deleting the task. Because the default value for the deleteRule parameter is nullify, you can create the relationship without explicitly specifying the delete rule:</p><pre>@Relationship(inverse: \SubTask.task)<br>var subTasks: [SubTask] = []</pre><h3>Saving your models into local storage</h3><p>Before SwiftData can examine your models and generate the required schema, you need to tell it — at runtime — which models to persist, and optionally, the configuration to use for the underlying storage. For example, you may want the storage to exist only in memory when running tests, or to use a specific CloudKit container when syncing model data across devices.</p><p>To set up the default storage, use the <a href="https://developer.apple.com/documentation/SwiftUI/View/modelContainer(for:inMemory:isAutosaveEnabled:isUndoEnabled:onSetup:)-18hhy">modelContainer(for:inMemory:isAutosaveEnabled:isUndoEnabled:onSetup:)</a> view modifier and specify the array of model types to persist:</p><pre>import SwiftUI<br><br>@main<br>struct SwiftDataProApp: App {<br>    var body: some Scene {<br>        WindowGroup {<br>            NavigationView {<br>                ContentView()<br>                    .modelContainer(for: [Task.self])<br>            }<br>        }<br>    }<br>}</pre><p>You can see that we used the view modifier modelContainer and we set Task.self at the very top of the view hierarchy so all nested views inherit the properly configured environment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sekXacDGxrsQAUu5SqgVgw.png" /></figure><p>You can see that inMemory is false which means all the changes will be saved into the local storage and isAutosaveEnabled is true means each time you change your data in the models you will not need to explicitly call save, as all the changes will be saved automatically.</p><p>After that we need to manage instances of your model classes at runtime, so we use a <em>model context </em>which is responsible for the in-memory model data and coordination with the model container to successfully persist that data and if you are using SwiftUI you can get the context for your model container that’s bound to the main actor by accessing <a href="https://developer.apple.com/documentation/SwiftUI/EnvironmentValues/modelContext">modelContext</a> environment variable:</p><pre>import SwiftUI<br>import SwiftData<br><br><br>struct ContentView: View {<br>    @Environment(\.modelContext) private var context<br>}</pre><p>After that we need to create <em>Task </em>Data and to enable SwiftData to persist a model instance we call insert into the context</p><pre> Button(&quot;Save&quot;) {<br>   let task = Task(name: text)<br>   modelContext.insert(task)<br>}</pre><h3>Fetch models for display</h3><p>After you begin persisting model data, you’ll likely want to retrieve the data as model instances, and display those instances in a view, SwiftData provides the <a href="https://developer.apple.com/documentation/swiftdata/query">Query</a> property wrapper.</p><p>To fetch model instances, and optionally apply search criteria and a preferred sort order, use @Query in your SwiftUI view. The @Model macro adds Observable conformance to your model classes, enabling SwiftUI to refresh the containing view whenever changes occur to any of the fetched instances.</p><pre>@Query(sort: \Task.name) var tasks: [Task]<br><br>var body: some View {<br>  List {<br>    ForEach(tasks) { task in<br>        NavigationLink {<br>            TaskDetailView(task: task)<br>                .navigationTitle(task.name)<br>        } label: {<br>            TaskCellView(task: task)<br>        }<br>    }<br>  }<br>}</pre><h3>Here’s the full code, easy and powerful 😍</h3><pre>import SwiftUI<br>import SwiftData<br><br>struct ContentView: View {<br>    @Environment(\.modelContext) private var modelContext<br>    @State var text: String = &quot;&quot;<br>    <br>    @Query(sort: \Task.name) var tasks: [Task]<br>    <br>    var body: some View {<br>        VStack {<br>            TextField(&quot;Add your Task...&quot;, text: $text)<br>            <br>            Button(&quot;Save&quot;) {<br>                let task = Task(name: text)<br>                modelContext.insert(task)<br>            }<br>            <br>            List {<br>                ForEach(tasks) { task in<br>                    NavigationLink {<br>                        TaskDetailView(task: task)<br>                            .navigationTitle(task.name)<br>                    } label: {<br>                        TaskCellView(task: task)<br>                    }<br>                }<br>            }<br>        }<br>        .padding()<br>    }<br>}<br><br>struct TaskDetailView: View {<br>    @State var text: String = &quot;&quot;<br>    let task: Task<br>    <br>    var body: some View {<br>        VStack {<br>            TextField(&quot;Add your Sub-Task...&quot;, text: $text)<br>            <br>            Button(&quot;Save&quot;) {<br>                let subTask = SubTask(name: text)<br>                task.tasks.append(subTask)<br>            }<br>            <br>            List {<br>                ForEach(task.tasks) { task in<br>                    Text(task.name)<br>                }<br>            }<br>        }<br>        .padding()<br>    }<br>}<br><br>struct TaskCellView: View {<br>    let task: Task<br>  <br>    var body: some View {<br>        VStack(alignment: .leading) {<br>            Text(task.name)<br>                .font(.headline)<br>            Text(&quot;Count: \(task.tasks.count)&quot;)<br>                .font(.caption)<br>        }<br>    }<br>}<br><br>@Model<br>final class Task {<br>    @Attribute(.unique)<br>    let name: String<br>    <br>    @Relationship(deleteRule: .cascade, inverse: \SubTask.task)<br>    var tasks: [SubTask] = []<br>    <br>    init(name: String) {<br>        self.name = name<br>    }<br>}<br><br><br>@Model<br>final class SubTask {<br>    let name: String<br>    var task: Task?<br>    <br>    init(name: String) {<br>        self.name = name<br>    }<br>}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7d39d1b79f98" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/learn-swiftdata-with-swiftui-7d39d1b79f98">Learn SwiftData with SwiftUI</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Swift Async and Await]]></title>
            <link>https://medium.com/swlh/swift-async-and-await-3e99f0fca5db?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/3e99f0fca5db</guid>
            <category><![CDATA[actors]]></category>
            <category><![CDATA[concurrency]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[task-group]]></category>
            <category><![CDATA[swiftui]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Sat, 16 Sep 2023 19:52:19 GMT</pubDate>
            <atom:updated>2023-09-16T19:52:19.763Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*o9zN0FIq_L6coX_-" /><figcaption>Photo by <a href="https://unsplash.com/@steve_j?utm_source=medium&amp;utm_medium=referral">Steve Johnson</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h4>Asynchronous code</h4><p><em>Asynchronous code</em> can be suspended and resumed later, although only one piece of the program executes at a time. Suspending and resuming code in your program lets it continue to make progress on short-term operations like updating its UI while continuing to work on long-running operations like fetching data over the network or parsing files.</p><h4><em>Parallel code</em></h4><p><em>Parallel code</em> means multiple pieces of code run simultaneously — for example, a computer with a four-core processor can run four pieces of code at the same time, with each core carrying out one of the tasks.</p><h4><em>What is Async and Await</em>?</h4><p><em>An asynchronous function</em> in Swift can give up the thread that it’s running on, which lets another asynchronous function run on that thread while the first function is blocked. When an asynchronous function resumes, Swift doesn’t make any guarantee about which thread that function will run on.</p><p>To indicate that a function is asynchronous, you write the async keyword in its declaration after its parameters</p><p>When calling an asynchronous method, execution suspends until that method returns, so you have to write await in front of the call to mark the possible suspension point. Inside an asynchronous method, the flow of execution is suspended <em>only</em> when you call another asynchronous method which means every possible suspension point is marked with await.</p><p>So Imagine that we need to download a photo, so we will create a function which does the network request and when the data comes back we call the completion closure to notify the caller like this:</p><pre>func downloadImage(from url: URL, completion: @escaping (UIImage?) -&gt; ()) {<br>  URLSession.shared.dataTask(with: URLRequest(url: url)) { data, response, error in<br>      if let data = data,<br>         let httpResponse = response as? HTTPURLResponse,<br>         httpResponse.statusCode &gt;= 200 &amp;&amp;  httpResponse.statusCode &lt;= 300 {<br>          completion(UIImage(data: data))<br>      } else if error != nil {<br>          completion(nil)<br>      }<br>  }.resume()<br>}</pre><p>So <a href="https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md">SE-0296</a> gave us a super sweet away to handle that by writing async to the function and use await to wait to the request to finish and download the photo data.</p><pre>func downloadImage(from url: URL) async -&gt; UIImage? {<br>  do {<br>      let (data, response) = try await URLSession.shared.data(from: url)<br>      if let httpResponse = response as? HTTPURLResponse,<br>         httpResponse.statusCode &gt;= 200 &amp;&amp;  httpResponse.statusCode &lt;= 300 {<br>          return UIImage(data: data)<br>      }<br>      return nil<br>  } catch {<br>      return nil<br>  }<br>}</pre><p>You can see that we just got rid of the <em>completion closure</em> from the first function and added <em>async/await</em> to the second function.</p><h4>How to use Async/Await to avoid Pyramid of doom</h4><p>Imagine that we need to execute a sequence of simple asynchronous operations which always requires deeply-nested closures, like imagine that you need to download an image, then resize it, decode it and finally upload it and notify when its done</p><pre>func processImage(from url: URL, completion: @escaping (Bool) -&gt; ()) {<br>    downloadImage(from: url) { image in<br>        resize(image: image) { resizedImage in<br>            decode(image: image) { decodedImage in<br>                upload(image: decodedImage) { response<br>                    completion(response.sccuess)<br>                }<br>            }<br>        }<br>    }<br>}</pre><p>So after <a href="https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md">SE-0296</a> gave us a super sweet away to handle that we can write the code super clean and neat like this:</p><pre>func processImage(from url: URL) async -&gt; Bool{<br>    let image = await downloadImage(from: url)<br>    let resizedImage = await resize(image: image)<br>    let decodedImage = await decode(image: resizedImage)<br>    let response = await upload(image: decodedImage)            <br>    return response.isSccuess<br>}</pre><ul><li>We started by downloading the image and because <em>downloadImage </em>function is async we have to use await which suspends execution while it waits for that function to return.</li><li>While this code’s execution is suspended, some other concurrent code in the same program runs. For example, maybe a long-running background task continues updating a list of new photo galleries. That code also runs until the next suspension point, marked by await, or until it completes.</li><li>After <em>downloadImage</em> returns, the code will continue execution starting at that point. It assigns the value that was returned to image.</li><li>The next await marks the call to the <em>resize(image:)</em> function and again the code pauses execution until that function returns, giving other concurrent code an opportunity to run.</li><li>After <em>resize(image:)</em> returns, the code will continue execution starting at that point. It assigns the value that was returned to resizedImage.</li><li>and so on until the all the async functions finished their work and finally return the state of the response.</li></ul><p>The possible suspension points in your code marked with await indicate that the current piece of code might pause execution while waiting for the asynchronous function or method to return. Swift suspends the execution of your code on the <em>current thread</em> and runs some other code on that thread instead. Because code with await needs to be able to suspend execution, only certain places in your program can call asynchronous functions or methods:</p><ul><li>Code in the body of an asynchronous function, method, or property.</li><li>Code in the static main() method of a structure, class, or enumeration that’s marked with @main.</li><li>Code in an unstructured child task.</li></ul><h4>Calling Asynchronous Functions in Parallel</h4><p>Calling an asynchronous function with await runs only one piece of code at a time. While the asynchronous code is running, the caller waits for that code to finish before moving on to run the next line of code.</p><p>As in the previous example each function had to wait to the previous function to return its result to continue executing the next function, so what about if you need to run more than one <em>async </em>function in the same time?</p><p>To call an asynchronous function and let it run in parallel with code around it, write async in front of let when you define a constant, and then write await each time you use the constant, so imagine that you need to download 4 photos</p><pre>async let image1 = downloadImage(from: url1)<br>async let image2 = downloadImage(from: url2)<br>async let image3 = downloadImage(from: url3)<br>async let image4 = downloadImage(from: url4)<br><br>let images = await [image1, image2, image3, image4]</pre><p>All 4 calls to <em>downloadImage </em>will<em> </em>start without waiting for the previous one to complete, and none of these function calls are marked with await because the code doesn’t suspend to wait for the function’s result. Instead, execution continues until the line where images is defined — at that point, the program needs the results from these asynchronous calls, so you write await to pause execution until all 4 images finish downloading.</p><h4>Task Groups</h4><p>Lets say that we have an array has bunch of <em>urls</em> and we need to download the image for each url, but we need to execute all the network requests in the same time parallel.</p><p><a href="https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md">SE-0304</a> gave us <em>Task Group</em> which defines a scope in which one can create new child tasks programmatically. As the child tasks within the task group scope must complete when the scope exits, and will be implicitly cancelled first if the scope exits with a thrown error.</p><p>The withTaskGroup API gives us access to a task group, and controls the lifetime of the <em>child tasks</em> we subsequently add to the group using its addTask() method. By the time withTaskGroup finishes executing, we know that all of the subtasks have completed.</p><pre>func download() async -&gt; [UIImage] {<br>  let urls = [<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br>      URL(string: &quot;https://images.unsplash.com/photo-1575936123452-b67c3203c357&quot;)!,<br> ]<br> <br>  return await withTaskGroup(of: UIImage.self) { group in<br>      for url in urls {<br>          group.addTask {<br>              await self.downloadImage(url: url)!<br>          }<br>      }<br>      defer {<br>          group.cancelAll()<br>      }<br>      return await group.reduce(into: [UIImage]()) {<br>          $0.append($1)<br>      }<br>  }<br>}</pre><p>We created withTaskGroup and inside we create a new task for each <em>url </em>to download the image for each url and after than we await for the result of the group to return all the downloaded images in the same time.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3e99f0fca5db" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/swift-async-and-await-3e99f0fca5db">Swift Async and Await</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to use Swift @MainActor and @globalActor]]></title>
            <link>https://blog.devgenius.io/how-to-use-mainactor-and-globalactor-d5fd3794903d?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/d5fd3794903d</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[concurrency]]></category>
            <category><![CDATA[race-condition]]></category>
            <category><![CDATA[actors]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Fri, 08 Sep 2023 21:45:10 GMT</pubDate>
            <atom:updated>2023-09-13T14:54:08.453Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3x2N9DeT0zphC7Lz" /><figcaption>Photo by <a href="https://unsplash.com/@marusyaionova?utm_source=medium&amp;utm_medium=referral">Maria Ionova</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><a href="https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md">Actors</a> are a new kind of reference type that protect their instance data from concurrent access. Swift actors achieve this with <em>actor isolation</em>, which ensures (at compile time) that all accesses to that instance data go through a synchronization mechanism that serializes execution.</p><p>Actors are fantastic for isolating instance data, providing a form of reference type that can be used in concurrent programs without introducing data races. However, when the data that needs to be isolated is scattered across a program, or is representing some bit of state that exists outside of the program, bringing all of that code and data into a single actor instance might be impractical (say, in a large program) or even impossible (when interacting with a system where those assumptions are pervasive).</p><h4># Defining global actors</h4><p>A global actor is a globally-unique actor identified by a type. That type becomes a custom attribute. Any declaration can state that it is actor-isolated to that particular global actor by naming the global actor type as an attribute, at which point all of the normal actor-isolation restrictions come into play: the declaration can only be synchronously accessed from another declaration on the same global actor, but can be asynchronously accessed from elsewhere.</p><p>A global actor is a type that has the <a href="https://developer.apple.com/documentation/swift/globalactor">@globalActor</a> attribute and contains a static property named <em>shared</em> that provides a shared instance of an actor.</p><pre>@globalActor actor UserProfileActor {<br>    static var shared = UserProfileActor()<br>}</pre><p>A global actor type can be a <em>struct</em>, <em>enum</em>, <em>actor</em>, or <em>final class</em>. It is essentially just a marker type that provides access to the actual shared actor instance via shared. The shared instance is a globally-unique actor instance that becomes synonymous with the global actor type, and will be used for synchronizing access to any code or data that is annotated with the global actor.</p><p>Global actors implicitly conform to the <strong><em>GlobalActor</em></strong> protocol, which describes the shared requirement. The conformance of a <a href="https://developer.apple.com/documentation/swift/globalactor">@globalActor</a> type to the GlobalActor protocol must occur in the same source file as the type definition, and the conformance itself cannot be conditional.</p><pre>/// A type that represents a globally-unique actor that can be used to isolate<br>/// various declarations anywhere in the program.<br>///<br>/// A type that conforms to the `GlobalActor` protocol and is marked with<br>/// the `@globalActor` attribute can be used as a custom attribute. Such types<br>/// are called global actor types, and can be applied to any declaration to<br>/// specify that such types are isolated to that global actor type. When using<br>/// such a declaration from another actor (or from nonisolated code),<br>/// synchronization is performed through the shared actor instance to ensure<br>/// mutually-exclusive access to the declaration.<br>@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)<br>public protocol GlobalActor {<br><br>    /// The type of the shared actor instance that will be used to provide<br>    /// mutually-exclusive access to declarations annotated with the given global<br>    /// actor type.<br>    associatedtype ActorType : Actor<br><br>    /// The shared actor instance that will be used to provide mutually-exclusive<br>    /// access to declarations annotated with the given global actor type.<br>    ///<br>    /// The value of this property must always evaluate to the same actor<br>    /// instance.<br>    static var shared: Self.ActorType { get }<br><br>    /// The shared executor instance that will be used to provide<br>    /// mutually-exclusive access for the global actor.<br>    ///<br>    /// The value of this property must be equivalent to `shared.unownedExecutor`.<br>    static var sharedUnownedExecutor: UnownedSerialExecutor { get }<br>}</pre><h4># Defining MainActor</h4><p>Its a globally unique actor who performs its tasks on the <em>main</em> thread. You can use it for properties, methods, instances, and closures to perform tasks on the main thread. Proposal <a href="https://github.com/apple/swift-evolution/blob/main/proposals/0316-global-actors.md">SE-0316 Global Actors</a>.</p><pre>/// A singleton actor whose executor is equivalent to the main<br>/// dispatch queue.<br>@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)<br>@globalActor final public actor MainActor : GlobalActor {<br><br>    /// The shared actor instance that will be used to provide mutually-exclusive<br>    /// access to declarations annotated with the given global actor type.<br>    ///<br>    /// The value of this property must always evaluate to the same actor<br>    /// instance.<br>    public static let shared: MainActor<br><br>    /// Retrieve the executor for this actor as an optimized, unowned<br>    /// reference.<br>    ///<br>    /// This property must always evaluate to the same executor for a<br>    /// given actor instance, and holding on to the actor must keep the<br>    /// executor alive.<br>    ///<br>    /// This property will be implicitly accessed when work needs to be<br>    /// scheduled onto this actor.  These accesses may be merged,<br>    /// eliminated, and rearranged with other work, and they may even<br>    /// be introduced when not strictly required.  Visible side effects<br>    /// are therefore strongly discouraged within this property.<br>    @inlinable nonisolated final public var unownedExecutor: UnownedSerialExecutor { get }<br><br>    /// The shared executor instance that will be used to provide<br>    /// mutually-exclusive access for the global actor.<br>    ///<br>    /// The value of this property must be equivalent to `shared.unownedExecutor`.<br>    @inlinable public static var sharedUnownedExecutor: UnownedSerialExecutor { get }<br><br>    @inlinable nonisolated final public func enqueue(_ job: UnownedJob)<br><br>    /// The type of the shared actor instance that will be used to provide<br>    /// mutually-exclusive access to declarations annotated with the given global<br>    /// actor type.<br>    public typealias ActorType = MainActor<br>}</pre><p>Imagine when we need to fetch the user pofile photo, we do network request and when the response came we switch to the main thread, we used to do this:</p><pre>func fetchProfilePhoto() async {<br>    // Here we do the normal Netwrok Request fo fetch the profile photo<br>    <br>    DispatchQueue.main.async {<br>        // Here we switch to the main thread to update the profile photo.<br>    }<br>}</pre><p>So now after having @<em>MainActor</em> we don’t need to use <em>DispatchQueue</em> anymore we can just label the function to <em>@MainActor </em>and <strong>it will execute the logic on the main thread</strong> like this:</p><pre>@MainActor<br>func fetchProfilePhoto() {<br>    // Here we do the normal Netwrok Request fo fetch the profile photo<br>    // After the request is done, we dont need to switch to Main thread anymore as @MainActor will take care for us.<br>}</pre><h4>#Using actors on functions and variable</h4><p>You can label the variables as well to make the access happens only on the main thread</p><pre>final class User {<br>    @MainActor var name: String?<br>    <br>    @MainActor func update(name: String) {<br>        self.name = name<br>    }<br>}</pre><p>If we tried to update the name in the <em>User </em>class, our compiler will complain as we can access <em>name</em> variable only from the <em>main</em> thread so we have to fix it by labeling <em>update</em> function to <em>@MainActor </em>as well.</p><h4>#Using actors on a class</h4><p>If we wanna make everything in the class be executed on the <em>main</em> thread, we can mark the class with <em>@MainActor</em></p><pre>@MainActor<br>final class UserViewModel {<br>    func updateProfilePhoto() {<br>        print(&quot;Update the profile photo done on MainThread: \(Thread.isMainThread)&quot;)<br>        print(&quot;Update the profile photo done on Thread: \(Thread.current)&quot;)<br>    }<br>    <br>    @UserProfileActor<br>    func fetchProfilePhoto() async {<br>        print(&quot;Fetch the profile photo done on MainThread: \(Thread.isMainThread)&quot;)<br>        print(&quot;Fetch the profile photo done on Thread: \(Thread.current)&quot;)<br>        await updateProfilePhoto()<br>    }<br>}<br><br>@globalActor actor UserProfileActor {<br>    static var shared = UserProfileActor()<br>}</pre><h4># But how can we use this GlobalActor along with MainActor?</h4><p>Imagine that you need to make everything in the class be executed on the <em>main </em>thread but in the same time there is a part of this class needs to be executed on a <strong><em>different</em></strong> thread, here comes the usage of global actor.</p><p>The function <em>fetchProfilePhoto </em>is labeled as <em>@UserProfileActor </em>which we did create earlier, then the fetch itself will be on the global actor like a different thread but the update itself will be on the main actor like <em>main</em> thread.</p><pre>Fetch the profile photo done on MainThread: false<br>Fetch the profile photo done on Thread: &lt;NSThread: 0x600000c34940&gt;{number = 7, name = (null)}<br><br>Update the profile photo done on MainThread: true<br>Update the profile photo done on Thread: &lt;_NSMainThread: 0x600000c280c0&gt;{number = 1, name = main}</pre><p>As we can see that both of the logic has been done on different threads.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d5fd3794903d" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/how-to-use-mainactor-and-globalactor-d5fd3794903d">How to use Swift @MainActor and @globalActor</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to build Alamofire Network Layer with Protocol-Oriented Programming and Combine]]></title>
            <link>https://blog.devgenius.io/how-to-build-alamofire-network-layer-with-protocol-oriented-programming-and-combine-4de005290566?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/4de005290566</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[alamofire]]></category>
            <category><![CDATA[network]]></category>
            <category><![CDATA[protocol-oriented]]></category>
            <category><![CDATA[combine]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Fri, 11 Dec 2020 22:58:00 GMT</pubDate>
            <atom:updated>2020-12-12T10:02:39.224Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*mgt6GDITALeVigIj" /><figcaption>Photo by <a href="https://unsplash.com/@alinnnaaaa?utm_source=medium&amp;utm_medium=referral">Alina Grubnyak</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>What is Protocol-Oriented Programming?</h3><p>Protocol-Oriented Programming is a new programming paradigm which is used by Swift. In the Protocol-Oriented approach, we start designing our system by defining protocols then the protocol extensions, protocol inheritance, and protocol compositions which allow us to add a new functionality not only to one type, but to a whole collection of types that all conform to the same protocol.</p><p>The value types in Swift like struct or enum cannot inherit from other structs or enums which means we cannot use inheritance with value types, but the value types can inherit from protocols, even multiple protocols which is the most powerful feature of Swift which gives us much reuse and less redundancy of the code. Highly recommended to watch <a href="https://developer.apple.com/videos/play/wwdc2015/408">Protocol-Oriented Programming in Swift WWDC</a> and read more about <a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c">Apple Combine</a>.</p><p>Let’s say we have a User and the user has an email and we need to check if this email is valid or not, so let’s start by this sequence:</p><h4>1- Define protocol</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1b89b42208a461c421c5206186317320/href">https://medium.com/media/1b89b42208a461c421c5206186317320/href</a></iframe><ul><li>Define the EmailValidator protocol and the inputs which the protocol will need like email.</li></ul><h4><strong>2- Extend Protocol</strong></h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7e570e8d4ecf219752afec4d4f454721/href">https://medium.com/media/7e570e8d4ecf219752afec4d4f454721/href</a></iframe><ul><li>Extend the protocol and apply all the logic we need to validate if the email is valid or not.</li></ul><h4>3- Apply Protocol</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/102f4c558522fa95b8a32ce98d90cfc1/href">https://medium.com/media/102f4c558522fa95b8a32ce98d90cfc1/href</a></iframe><ul><li>Then apply the EmailValidator into the User struct and without writing any code to validate the email, the user will inherit that. It’s super easy, huh? 😍</li><li>We can apply the EmailValidator protocol to any class or struct which need to validate the email without writing any more code to do that. 🎉</li></ul><h4>4- Test with Protocol</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0869dfb10745a11c02b6c8cf14d4c038/href">https://medium.com/media/0869dfb10745a11c02b6c8cf14d4c038/href</a></iframe><ul><li>The most powerful thing about using POP is the <em>testing</em>, let’s say that we need for some reasons to return all the time that the email is invalid, all we need is to extend the EmailValidator where is being conformed by MockUser and override the logic of isValidEmail to always return false super easy, I love it!.</li></ul><p>That’s how we can use the Protocol-Oriented Programming in Swift, it’s so easy to reuse and test and thence we will apply the same concept on the Network layer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/307/1*UO0FtN9C7A4wf_-ojUuFZg.gif" /></figure><ul><li>In this Demo will learn how to call the network request to get the movies popular list, you can check all the code at the end of this article.</li></ul><h4>1- Define protocol</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0d76f1db3a880b614ce8ae67123281ea/href">https://medium.com/media/0d76f1db3a880b614ce8ae67123281ea/href</a></iframe><ul><li>Define the URLRequestBuilder protocol which conforms URLRequestConvertible protocol which is part from Alamofire.</li><li>Then we need to define all the inputs which our protocol needs, but before doing that we need to check the URLRequestConvertible protocol.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AiBo7XPqsThRWR4osw5alg.png" /></figure><ul><li>When we did check URLRequestConvertible protocol, will find only one function asURLRequest() which will returns URLRequest.</li><li>So we need to know how we can buildURLRequest, so will define all the inputs which the network request will need like: URL, path, ParameterEncoding, HTTPHeaders, HTTPMethod.</li></ul><h4>2- Extend Protocol</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a423dc2608e4607f835476115f0879bd/href">https://medium.com/media/a423dc2608e4607f835476115f0879bd/href</a></iframe><ul><li>Do URLRequestBuilder extension and add the implementation for each input which will depend on the request like: if the httpMethod is .get then the encoding will be URLEncoding and if its .post then the encoding will be JSONEncoding.</li><li>Build URLRequest with the httpMethod and add the header values for the request.</li><li>Try to encode the urlRequest with the parameters and return it in asURLRequest function.</li></ul><h4>3- Apply Protocol</h4><ul><li>In this example we have two network calls one get the popular movies list and the other one search the movies, then we need to apply our URLRequestBuilder protocol into them, so let see how.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0d23701605e0bd251846525aaf8d3f06/href">https://medium.com/media/0d23701605e0bd251846525aaf8d3f06/href</a></iframe><ul><li>Create MoviesAPIs enum which will extend our protocol URLRequestBuilder and has the two cases for the two network calls.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/64ba9194e2b45da88d60cc49915fd651/href">https://medium.com/media/64ba9194e2b45da88d60cc49915fd651/href</a></iframe><ul><li>In MoviesAPIs extension implement the path for each case/call.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/99e218ef21d534f0fc693ae1fa8967f5/href">https://medium.com/media/99e218ef21d534f0fc693ae1fa8967f5/href</a></iframe><ul><li>In MoviesAPIs extension implement the parameters for each case/call like: we need to have language, api_key, page for <strong>getPopularList</strong> case/call.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c9733d6508892d62bb1fff4e2dee2c33/href">https://medium.com/media/c9733d6508892d62bb1fff4e2dee2c33/href</a></iframe><ul><li>In MoviesAPIs extension implement the http method for each case/call.</li></ul><h4>4- Create NetworkService</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/728b5da387f92aff470f849bfcfb54fe/href">https://medium.com/media/728b5da387f92aff470f849bfcfb54fe/href</a></iframe><ul><li>Create NetworkServiceProtocol protocol which have one function to execute URLRequest.</li><li>In NetworkServiceProtocol will implement execute function and now Alamofire supports <a href="https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#using-alamofire-with-combine">Combine</a>.</li><li>First we need to get DataResponsePublisher by calling publishDecodable with the model type which we will decode to codable.</li><li>Then we need to subscribe the publisher on the background queue to execute our network call.</li><li>Then we need to receive the publisher on the main queue to handle all UI changes.</li><li>Then we need to sink to the publisher to get the result and return in the completion.</li><li>Finally we need to return the AnyCancellable from Sink function so we can cancel it anytime.</li></ul><h4>4- How to use NetworkService</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/32b9bcef199f616e0fb80d61f76a5321/href">https://medium.com/media/32b9bcef199f616e0fb80d61f76a5321/href</a></iframe><ul><li>Just create the network service class and execute the network request like Endpoints.getPopularList(<strong>self</strong>.pager.nextPage).resolve() and add the type of the response like MoviesResponse.<strong>self </strong>and the network layer itself will care for the rest, super easy!<strong> 😃</strong></li></ul><p>Hope you enjoyed as I did 😃🎉 and if so feel free to clap 😄 and share with your friends, Its always pleasure to share with people, here’s all the source code if you would like to check as well:</p><p><a href="https://github.com/deda9/MovizySwiftUI">deda9/MovizySwiftUI</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4de005290566" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/how-to-build-alamofire-network-layer-with-protocol-oriented-programming-and-combine-4de005290566">How to build Alamofire Network Layer with Protocol-Oriented Programming and Combine</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Learn how to play and record audio on iOS AVFoundation]]></title>
            <link>https://blog.devgenius.io/ios-avfoundation-series-part-1-4eebaa837d9c?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/4eebaa837d9c</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[audio]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[avfoundation]]></category>
            <category><![CDATA[record]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Sun, 06 Dec 2020 18:31:11 GMT</pubDate>
            <atom:updated>2020-12-07T20:59:17.161Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*lJ7QYjveH39zg_Yr" /><figcaption>Photo by <a href="https://unsplash.com/@markusspiske?utm_source=medium&amp;utm_medium=referral">Markus Spiske</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><strong>AVFoundation</strong> is a multimedia framework with APIs in Objective-C and Swift which provides high-level services for working with time-based audiovisual media and combines six major technology areas which will go through each one in more details up and running, so let’s start with the first area in this article:</p><ul><li><a href="https://developer.apple.com/documentation/avfoundation/audio_playback_recording_and_processing">Audio Playback, Recording, and Processing</a></li><li><a href="https://developer.apple.com/documentation/avfoundation/media_composition_and_editing">Media Composition and Editing</a></li><li><a href="https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture">Cameras and Media Capture</a></li><li><a href="https://developer.apple.com/documentation/avfoundation/media_playback_and_selection">Media Playback and Selection</a></li><li><a href="https://developer.apple.com/documentation/avfoundation/media_assets_and_metadata">Importing and exporting audiovisual media on Apple platforms.</a></li><li><a href="https://developer.apple.com/documentation/avfoundation/speech_synthesis">Speech Synthesis and Convert text to spoken audio</a></li></ul><h3>Play an audio with AVAudioPlayer</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1f42559d4402cdd9c550b04e801cfa76/href">https://medium.com/media/1f42559d4402cdd9c550b04e801cfa76/href</a></iframe><ul><li>Create the songURL for the audio which wanna play.</li><li>Create the player and hold the reference of AVAudioPlayer because if we don’t have a reference, the player will be deallocated and can’t play the audio.</li><li>Need to set the AVAudioPlayerDelegate to update the UI when the audio is finished.</li><li>Set numberOfLoops to .max in case wanna repeat playing this audio to infinity.</li><li>prepareToPlay: preloads buffers and acquires the audio hardware needed for playback, which minimizes the lag between calling the play() method and the start of sound output, but calling the stop() method, or allowing a sound to finish playing, undoes this setup.</li></ul><h4>Trace the current playing time</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c108bc8b625c54807b17e26e0182c99b/href">https://medium.com/media/c108bc8b625c54807b17e26e0182c99b/href</a></iframe><ul><li>You can trace the current time by creating Timer which will repeatedly reschedule itself each 0.2 second and use the currentTime of the current playing audio.</li><li>Don’t forget to hold the reference to the Timer, otherwise will not work.</li><li>Don’t forget to invalidate the Timer when deinit is called to avoid crashes.</li></ul><h4>Change the playing rate</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6771e8b2fb564582867e601e38f08f02/href">https://medium.com/media/6771e8b2fb564582867e601e38f08f02/href</a></iframe><ul><li>If the audio is already playing, we can’t change the rate unless we replace the old player with a new one.</li><li>Set enableRate to true before set the rate value.</li><li>Play the new created player.</li></ul><h4>Handle the UI when the audio is finished</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c7f81a81a4471872faa9db43d26fd03b/href">https://medium.com/media/c7f81a81a4471872faa9db43d26fd03b/href</a></iframe><ul><li>After setting the player delegate, we can update the UI when the audio is finished in audioPlayerDidFinishPlaying.</li></ul><h3>Recording Audio with AVAudioRecorder</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c25d19359a23bdec0551c08c44770067/href">https://medium.com/media/c25d19359a23bdec0551c08c44770067/href</a></iframe><ul><li>Recording audio requires a user’s permission to stop malicious apps doing malicious things. If the permission is granted, we’ll update the UI and start recording.</li><li>Create the AVAudioSession which acts as an intermediary between your app and the operating system. You use an audio session to communicate to the operating system the general nature of your app’s audio without detailing the specific behavior or required interactions with the audio hardware. You delegate the management of those details to the audio session, which ensures that the operating system can best manage the user’s audio experience.</li><li>We need to active the audio session before request the permission by setActive(true).</li><li>When the permission is granted we can start recording and update the UI to show that the recording started.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ovot0a3I17DJe2iub8DbjA.png" /></figure><ul><li>We need to set NSMicrophoneUsageDescription’s permission in the info.plist and describe why your app will use the microphone.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/87ef668655965797835b47acf544c10a/href">https://medium.com/media/87ef668655965797835b47acf544c10a/href</a></iframe><ul><li>We need to create the URL where we will save the recorded audio, so we will get the documentDirectory url and then append the name of the recored audio which can be any name and the extension, like newRecord.m4a.</li><li>We need to create the AVAudioRecorder and to do so we need to create the settings of the audio which will be recorded.</li><li>We have two types of the settings:</li><li><a href="https://developer.apple.com/documentation/avfoundation/avaudioplayer/1389359-settings"><strong>AVAudioPlayer Settings</strong></a> which contains the information about the sound associated with the player like:</li><li>1- <a href="https://developer.apple.com/documentation/avfoundation/avchannellayoutkey">AVChannelLayoutKey</a>: The corresponding value is an NSData object containing an AudioChannelLayout. <strong>Channel layout</strong> can be used to describe how your audio is organized, like Mono is just <strong>1</strong> <strong>channel</strong>, Stereo is 2 <strong>channel</strong>. Each individual <strong>channel</strong> stand for a source, and a <strong>channel layout</strong> is just a combinations of <strong>channels</strong></li><li>2- <a href="https://developer.apple.com/documentation/avfoundation/avencoderbitratekey">AVEncoderBitRateKey</a>: An integer that identifies the audio bit rate which is the amount of data encoded for a unit of time, and for streaming is usually referenced in megabits per second (Mbps) for video, and in kilobits per second (kbps) for audio. From a streaming perspective, a higher video bitrate means a higher quality video that requires more bandwidth.</li><li>3- <a href="https://developer.apple.com/documentation/avfoundation/avformatidkey">AVFormatIDKey</a>: A format identifier and it can be any value of <a href="https://developer.apple.com/documentation/coreaudiotypes/coreaudiotype_constants/1572096-audio_data_format_identifiers">Audio Data Format Identifiers</a>.</li><li>4- <a href="https://developer.apple.com/documentation/avfoundation/avnumberofchannelskey">AVNumberOfChannelsKey</a>: The number of channels expressed as an NSNumber integer value.</li><li>5- <a href="https://developer.apple.com/documentation/avfoundation/avsampleratekey">AVSampleRateKey</a>: A sample rate, in hertz, expressed as an NSNumber floating point value which defines how many times per second a sound is sampled. Technically speaking, it is the frequency of samples used in a digital recording. The standard sample rate used for audio CDs is <em>44.1 kilohertz (44,100 hertz)</em>. The human ear can detect sounds from roughly <a href="https://techterms.com/definition/sample_rate"><em>20 hertz</em> to <em>20 kilohertz.</em></a></li><li><a href="https://developer.apple.com/documentation/avfoundation/avaudiorecorder/encoder_settings"><strong>AVAudioRecorder Settings</strong></a> which contains the information of the encoder which will encode the sound like:</li><li>1- <a href="https://developer.apple.com/documentation/avfoundation/avencoderaudioqualitykey">AVEncoderAudioQualityKey</a>: A constant from <a href="https://developer.apple.com/documentation/avfoundation/avaudioquality">AVAudioQuality</a> which is (.min, .low, .medium, .high, .max)</li><li>2- <a href="https://developer.apple.com/documentation/avfoundation/avencoderbitratekey">AVEncoderBitRateKey</a>: An integer that identifies the audio bit rate.</li><li>3- <a href="https://developer.apple.com/documentation/avfoundation/avencoderbitrateperchannelkey">AVEncoderBitRatePerChannelKey</a>: An integer that identifies the audio bit rate per channel.</li><li>4- <a href="https://developer.apple.com/documentation/avfoundation/avencoderbitratestrategykey">AVEncoderBitRateStrategyKey</a>: An AVAudioBitRateStrategy constant.</li><li>5- <a href="https://developer.apple.com/documentation/avfoundation/avencoderbitdepthhintkey">AVEncoderBitDepthHintKey</a>: An integer ranging from 8 through 32. A more effective way to improve the quality of digital audio is to increase the bit depth, which determines amplitude range of each sample</li><li>After creating the url and the settings we can create the recorder and then set the delegate (<a href="https://developer.apple.com/documentation/avfoundation/avaudiorecorderdelegate">AVAudioRecorderDelegate</a>) so we can use it later to update the UI when the recording is finished.</li><li>Before starting the actual recording we need to ask the user about the microphone permission.</li></ul><h4>Handle the UI when the recording is finished</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c4280a9351973d4712f7d6cf6ca647db/href">https://medium.com/media/c4280a9351973d4712f7d6cf6ca647db/href</a></iframe><ul><li>After setting the recorder the delegate, we can update the UI when the recoding is finished in audioRecorderDidFinishRecording function.</li></ul><h3>Manage audio behavior by AVAudioSession</h3><p><strong>AVAudioSession</strong> acts as an intermediary between your app and the operating system. You use it to communicate to the operating system the nature of your app’s audio without detailing the specific behavior or required interactions with the audio hardware. Delegating the management of those details to the audio session ensures optimal management of the user’s audio experience.</p><p>All iOS, tvOS, and watchOS apps have a default audio session that comes preconfigured with the following behavior:</p><ul><li>It supports audio playback, but disallows audio recording (tvOS doesn’t support audio recording).</li><li>In iOS, setting the Ring/Silent switch to silent mode silences any audio the app is playing.</li><li>In iOS, locking a device silences the app’s audio.</li><li>When the app plays audio, it silences any other background audio.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/54352969f4d368e4ab33f80d818e2c77/href">https://medium.com/media/54352969f4d368e4ab33f80d818e2c77/href</a></iframe><ul><li>The primary means of configuring your audio session is by setting its category. The precise behaviors associated with each category are not under your app’s control, but rather are set by the operating system, so your best strategy is to pick the category that most accurately describes your intentions for the audio behavior you want.</li><li>Certain categories support overriding their default behavior by setting one or more category options on the session . For instance, the default behavior associated with the <a href="https://developer.apple.com/documentation/avfoundation/avaudiosession/category/1616509-playback">playback</a> category interrupts other system audio when the session is activated. In most cases, a playback app needs this behavior. However, if you want your audio to mix with other system audio, you can override this behavior by setting the <a href="https://developer.apple.com/documentation/avfoundation/avaudiosession/categoryoptions/1616611-mixwithothers">mixWithOthers</a> option on the session <a href="https://developer.apple.com/documentation/avfoundation/avaudiosession/categoryoptions">AVAudioSession.CategoryOptions</a>.</li></ul><p><a href="https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html#//apple_ref/doc/uid/TP40007875-CH10"><strong>Audio Session category behavior</strong></a><strong>:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y2ZRc1TXYVyQqatAPlOv6w.png" /></figure><p><a href="https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html#//apple_ref/doc/uid/TP40007875-CH10"><strong>Modes and associated categories</strong></a><strong>:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jmXxEQ_UQs1eGstdw5AoTA.png" /></figure><h4><strong>Tips:</strong></h4><ul><li>For your app to continue playing audio when the Ring/Silent switch is set to silent and the screen is locked, make sure the <a href="https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/plist/info/UIBackgroundModes">UIBackgroundModes</a> audio key has been added to your app’s Info.plist file. This requirement is in addition to your using the correct category.</li><li>You can activate the audio session at any time after setting its category, but it’s generally preferable to defer this call until your app begins audio playback. Deferring the call ensures that you won’t prematurely interrupt any other background audio that may be in progress.</li></ul><p>Hope you enjoyed as I did 😃🎉 and if so feel free to clap 😄 and share with your friends, Its always pleasure to share with people, here’s all the source code if you would like to check as well:</p><p><a href="https://github.com/deda9/AVFoundationExample">deda9/AVFoundationExample</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4eebaa837d9c" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/ios-avfoundation-series-part-1-4eebaa837d9c">Learn how to play and record audio on iOS AVFoundation</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introduction into iOS Core Audio]]></title>
            <link>https://blog.devgenius.io/introduction-into-ios-core-audio-1ec9ea15c47c?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/1ec9ea15c47c</guid>
            <category><![CDATA[audio]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swif]]></category>
            <category><![CDATA[core-audio]]></category>
            <category><![CDATA[avfoundation]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Tue, 01 Dec 2020 20:19:34 GMT</pubDate>
            <atom:updated>2020-12-01T21:56:10.907Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1SNI5u2xEf83-bLq" /><figcaption>Photo by <a href="https://unsplash.com/@cdx2?utm_source=medium&amp;utm_medium=referral">C D-X</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Before starting playing, streaming, recording sounds or configure how your application and the operating system should respond to the interruptions, we need to take a small journey to the Core Audio and some definitions about the audio just to get the full picture. In the next parts will talk in more details up and running.</p><h3>What’s Core Audio?</h3><p>Core Audio is the digital audio infrastructure of iOS and OS X. It includes a set of software frameworks designed to handle the audio needs in your applications which is optimized for the computing resources available in a battery powered mobile platform.</p><p>Core Audio uses the notion of <em>proxy objects</em> to represent such things as files, streams, audio players, and so on. When you want your application to work with an on-disk audio file, for example, the first step is to instantiate an audio file object of type <a href="https://developer.apple.com/documentation/audiotoolbox/audiofileid">AudioFileID</a> which is declared as an opaque data.</p><pre>typealias AudioFileID = OpaquePointer</pre><p>You instantiate an audio file object and create an actual audio file tied to that object by calling the <a href="https://developer.apple.com/documentation/audiotoolbox/1502333-audiofilecreatewithurl">AudioFileCreateWithURL</a> function. The function gives you a reference to the new audio file object.</p><p>Apple has designed the software interfaces to Core Audio using a layered, cooperative, task-focused approach which are arranged into three layers:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/864/0*Xmg91CKWxcXF5ZGL.png" /><figcaption><a href="https://developer.apple.com/library/archive/documentation/MusicAudio/Conceptual/CoreAudioOverview/Art/core_audio_layers_2x.png">https://developer.apple.com/library/archive/documentation/MusicAudio/Conceptual/CoreAudioOverview/Art/core_audio_layers_2x.png</a></figcaption></figure><p><strong>Low Level Service Layer:</strong></p><ul><li>The I/O Kit which interacts with drivers.</li><li>The audio hardware abstraction layer (audio HAL) which provides a device-independent, driver-independent interface to hardware.</li><li>Core MIDI which provides software abstractions for working with MIDI (Musical Instrument Digital Interface) streams and devices.</li><li>Host Time Services which provides access to the computer’s clock.</li></ul><p><strong>Mid Level Service Layer:</strong></p><ul><li>Audio Converter Services lets applications work with audio data format converters.</li><li>Audio File Services supports reading and writing audio data to and from disk-based files.</li><li>Audio Unit Services and Audio Processing Graph Services let applications work with digital signal processing (DSP) plug-ins such as equalizers and mixers.</li><li>Audio File Stream Services supports building applications that can parse streams, such as for playing files streamed over a network connection.</li><li>Core Audio Clock Services supports audio and MIDI synchronization as well as time-base conversions.</li><li>Audio Format Services assists with managing audio data formats in your application.</li></ul><p><strong>High Level Service Layer:</strong></p><ul><li>Audio Queue Services lets you record, play, pause, loop, and synchronize audio.</li><li>The AVAudioPlayer supports playing and looping audio as well as implementing rewind and fast-forward.</li><li>Extended Audio File Services combines features from Audio File Services and Audio Converter services. It gives you a unified interface for reading and writing uncompressed and compressed sound files.</li><li>OpenAL is the Core Audio implementation of the open-source OpenAL standard for positional audio. It is best suited for games development.</li></ul><h3>What are the available frameworks which we can use?</h3><p>There are many audio frameworks which we can use, and here’s a short brief about each one. In the next parts will talk about each one in more details up and running.</p><ul><li>AVFoundation.framework provides the AVAudioPlayer class for audio playback and also provides the AVAudioEngine class for more sophisticated audio handling.</li><li>AudioToolbox.framework: manages the Audio Session and the behavior of your application’s audio in the context of a device.</li><li>AudioUnit.framework: let your applications work with audio plug-ins including audio units and codecs.</li><li>CoreAudio.framework supplies data types used across Core Audio as well as interfaces for the low-level services.</li><li>OpenAL.framework provides the interfaces to work with OpenAL and it’s more for games suited development.</li><li>CoreAudioKit.framework provides a small API for creating user interfaces for audio units <strong>(not available in iOS)</strong>.</li><li>CoreMIDI.framework lets applications work with MIDI data and configure MIDI networks <strong>(not available in iOS)</strong>.</li><li>CoreMIDIServer.framework lets MIDI drivers communicate with the OS X MIDI server <strong>(not available in iOS)</strong>.</li></ul><h3>Audio Data Formats</h3><p>You don’t need a detailed knowledge of audio data formats so that one set of code can work with any format supported by the operating system. An audio data format describes audio data such things as sample rate, bit depth, format flags or the number of frames in a packet of audio data.</p><p>Some audio file formats can contain just one sort of audio data format for instance, an MP3 file can contain only MP3 audio data. Other file formats such as Apple’s CAF format can contain a variety of audio data formats. You can find more details about <a href="https://developer.apple.com/documentation/coreaudiotypes/audiostreambasicdescription">AudioStreamBasicDescription</a></p><h3>Magic Cookies</h3><p>It refers to information included in <strong>audio</strong> file header used to describe data formats. The metadata gives a decoder the details it needs to properly decompress the file or stream. When converting audio data you must check to see if the format of the audio data you are attempting to convert has a magic cookie. If the audio data format has a magic cookie associated with it, you must add this information to the instance of the audio converter being used. This is done by using the AudioConverterSetProperty API along with the kAudioConverterDecompressionMagicCookie property and the magic cookie data blob.</p><h3>Audio Data Packets</h3><p>It’s as a collection of one or more frames. It is the smallest meaningful so it is the best unit of audio data to represent a unit of time in an audio file. You can use packets to calculate useful audio data buffer sizes. In order to communicate audio via networks the audio packets are sent to the network from the sending side and the receiving side picks up the audio packet and integrates the finely segmented digital signals to turn it back into an analogue signal which enables the original audio to be heard.</p><h3>Data Format Conversion</h3><p>To convert audio data from one format to another, you use an audio converter. You can make simple conversions such as changing sample rate or interleaving/deinterleaving. You can also perform complex conversions such as compressing or decompressing audio.</p><p>Three types of conversions are available:</p><ul><li>Decoding an audio format to linear PCM format.</li><li>Converting linear PCM data into a different audio format.</li><li>Converting between different variants of linear PCM</li></ul><h3>Playing Multiple Sounds Simultaneously</h3><p>To play multiple sounds simultaneously, create one playback audio queue object for each sound. For each audio queue, schedule the first buffer of audio to start at the same time using the AudioQueueEnqueueBufferWithParameters function.</p><p>Audio format is critical when you play sounds simultaneously on iPhone or iPod touch. This is because playback of certain compressed formats in iOS employs an efficient hardware codec. Only a single instance of one of the following formats can play on the device at a time:</p><ul><li>AAC</li><li>ALAC</li><li>MP3</li></ul><p>To play high quality, simultaneous sounds, use linear PCM or IMA4 audio.</p><h3>Audio Queue Services</h3><p>Audio Queue Services provides a straightforward, low overhead way to record and play audio. It lets your application use hardware recording and playback devices (such as microphones and loudspeakers) without knowledge of the hardware interface. It also lets you use sophisticated codecs without knowledge of how the codecs work.</p><p>You can use it to synchronize playback of multiple audio queues, to play sounds simultaneously, to independently control playback level of multiple sounds, and to perform looping.</p><h3>System Sounds: Alerts and Sound Effects</h3><p>To play short sound files when you do not need level, positioning, audio session, or other control. When you just want to play a short sound in the simplest way possible use System Sound Services which is declared in the Audio Toolbox framework. In iOS, sounds played using System Sound Services are limited to a maximum duration of 30 seconds.</p><p>In iOS, you call the AudioServicesPlaySystemSound function to immediately play a sound effect file that you designate. Alternatively, you can call AudioServicesPlayAlertSound when you need to alert the user. Each of these functions will invoke vibration on an iPhone if the user has set the silence switch.</p><h3>Digital Audio and Linear PCM</h3><p>Most Core Audio services use and manipulate audio in linear pulse-code-modulated (<em>linear PCM</em>) format, the most common uncompressed digital audio data format. Digital audio recording creates PCM data by measuring an analog audio signal’s magnitude at regular intervals (the <em>sampling rate</em>) and converting each sample to a numerical value.</p><p><em>Standard compact disc (CD) audio uses a sampling rate of 44.1 kHz, with a 16-bit integer describing each sample constituting the resolution or bit depth.</em></p><ul><li>A <em>sample</em> is single numerical value for a single channel.</li><li>A <em>frame</em> is a collection of time-coincident samples. For instance, a stereo sound file has two samples per frame, one for the left channel and one for the right channel.</li><li>A <em>packet</em> is a collection of one or more contiguous frames. In linear PCM audio, a packet is always a single frame. In compressed formats, it is typically more.</li></ul><p><em>The 16-bit integer samples in standard CD audio allow 65,536 possible values between silence and maximum level.</em></p><h3>Configuring an Audio Session</h3><p>An audio session is the intermediary between your app and the operating system that is used to configure your app’s audio behavior. Upon launch, your app is automatically provided with a singleton audio session. You configure it such as whether your audio should continue when the Ringer/Silent switch is flipped.</p><p>All iOS, tvOS, and watchOS apps have a default audio session that is preconfigured as follows:</p><ul><li>Audio playback is supported, but audio recording is disallowed.</li><li>In iOS, setting the Ring/Silent switch to silent mode silences any audio being played by the app.</li><li>In iOS, when the device is locked, the app’s audio is silenced.</li><li>When your app plays audio, any other background audio — such as audio being played by the Music app — is silenced.</li></ul><p>You can customize it to better suit your app’s needs by setting its category.</p><h3>Enabling Background Audio</h3><p>When you enable background audio your app’s audio can continue when users switch to another app or when they lock their iOS devices and to do so, you need to select your app’s target in Xcode and select the Capabilities tab. Under the Capabilities tab, set the Background Modes switch to ON and select the “Audio, AirPlay, and Picture in Picture” option from the list of available modes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vqg-UHNp-NIbB07wXe3rWQ.png" /></figure><p>Hope you enjoyed as I did 😃🎉 and if so feel free to clap 😄 and share with your friends, Its always pleasure to share with people. Stay tuned for the other parts while having real code examples.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1ec9ea15c47c" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/introduction-into-ios-core-audio-1ec9ea15c47c">Introduction into iOS Core Audio</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[iOS Core Data With Combine]]></title>
            <link>https://medium.com/swlh/ios-core-data-with-combine-c80373c5484?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/c80373c5484</guid>
            <category><![CDATA[core-data]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[observables]]></category>
            <category><![CDATA[publishers]]></category>
            <category><![CDATA[combine]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Fri, 20 Nov 2020 12:03:18 GMT</pubDate>
            <atom:updated>2020-11-28T22:56:41.627Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dHJPFl4RbLGyu6th" /><figcaption>Photo by <a href="https://unsplash.com/@jankolar?utm_source=medium&amp;utm_medium=referral">Jan Antonin Kolar</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Will talk about how we can use Apple Combine with Core Data but if you like to read more about Core Data itself and how can we use it to save, fetch and delete the entities you can read the previous article about <a href="https://medium.com/dev-genius/ios-core-data-with-sugar-syntax-ef53a0e06efe">Core Data with Sugar Syntax</a>.</p><p>First we will need to create a custom Combine Publisher and fortunately it’s super easy to do that we will need just 3 steps to do it but before doing that we need to understand how the publisher actually work, so let’s talk about that for a bit before applying our customer Publisher to the Core Data and we need to understand the <em>Publisher</em>, the<em> </em><em>Subscription </em>and the<em> </em><em>Subscriber</em></p><ul><li>The <em>Publisher</em> is just a simple internal protocol which has the <em>Failure</em> type (When our logic did fail the publisher will publish this error in the completion with failure case), the <em>Output</em> type (It is the result which our publisher will publish when did succeed) and receive&lt;S&gt;(subscriber:) function where we will make the the subscriber to successfully subscribe to the publisher.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rJLN-DNSX287OPpqgfLVeQ.png" /></figure><ul><li>When we extend that protocol we need to set the type for both of<em>Failure </em>and <em>Output.</em></li><li>Actually the publisher doesn&#39;t do the work, but every publisher is backed by a Subscription which will be our custom class which will extend Subscription where the magic happens.</li><li>The <em>Subscription</em> is just another simple internal protocol which has one function request(<strong>_</strong> demand:) which will have all our logic.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1vke297mj6BrwovAr8RyAw.png" /></figure><ul><li>The <em>Subscriber </em>is another simple internal protocol that declares a type that can receive input from a publisher.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zT0QjnUMB_OsqN3J2rxz-Q.png" /></figure><p>…and after we knew the Publisher’s components let’s go deep and start the 3 steps to make it happen 😃</p><h4>1- Create a struct and extend Publisher Protocol</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1f2ddcf1ae7a4a03c7823bce56a8c139/href">https://medium.com/media/1f2ddcf1ae7a4a03c7823bce56a8c139/href</a></iframe><p>1- Create CoreDataSaveModelPublisher which extends thePublisher.</p><p>2- Pass the NSManagedObjectContext property where we can use the context to save the entities into the Core Data.</p><p>3- Pass theAction property closure which will hold all the creation of the entities (NSManagedObjects) which will be executed later.</p><p>4- The Failure type will be NSError and the Output will be Bool just to tell us the process is succeeded or not.</p><p>5- Create a custom Subscription class which will do all the magic and pass all the properties which we will use later.</p><p>5- The subscriber successfully subscribed to the publisher in receive&lt;S&gt;(subscriber:.</p><h4>2- Create a Subscription class and extend Subscription Protocol</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ef016ed42e6aab7d92097f8fc1078c1c/href">https://medium.com/media/ef016ed42e6aab7d92097f8fc1078c1c/href</a></iframe><p>1- Create CoreDataSaveModelPublisher.Subscription which extends theSubscription which will hold the NSManagedObjectContext, Action and Subscriber.</p><p>2- Do the logic to save the entity into the Core Data in the function request(<strong>_</strong> demand:).</p><p>3- If the process succeeded then notify the Subscriber with the success value otherwise notify with completion: .failure(error).</p><p>4- Extend Cancellable to make our custom publisher is cancellable.</p><h4>3- Use the custom CoreDataSaveModelPublisher</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f41b8bf5e480bdcf5491515c2bf68bf2/href">https://medium.com/media/f41b8bf5e480bdcf5491515c2bf68bf2/href</a></iframe><p>1- After creating CoreDataSaveModelPublisher its the time to use it, create all the entities which we need to save into the Core Data and warp that block in aAction closure.</p><p>2- Then use the publisher(save: action) of coreDataStore (you can find it on the code repository) and then we can use sink, receive(on:) or subscribe(on:) as normal.</p><p>and here’s all the final publishers to Save &amp; Fetch &amp; Delete data into the Core Data:</p><p>1- Save any Entity into the Core Data by <strong>CoreDataSaveModelPublisher</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/06d135ed8da95a270a6f33e1048b026d/href">https://medium.com/media/06d135ed8da95a270a6f33e1048b026d/href</a></iframe><p>2- Fetch the data from the Core Data by <strong>CoreDataFetchResultsPublisher</strong>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eaa37a20bf783e3de931a52c2bbf1e38/href">https://medium.com/media/eaa37a20bf783e3de931a52c2bbf1e38/href</a></iframe><p>3- Delete any Entity from the Core Data by <strong>CoreDataDeleteModelPublisher</strong>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0aebfeeaafa4953a14e297ef4fa2ec70/href">https://medium.com/media/0aebfeeaafa4953a14e297ef4fa2ec70/href</a></iframe><p>Hope you enjoyed as I did 😃🎉 and if so feel free to clap and if you liked more feel free to clap more 😃 and share with your friends, Its always pleasure to share with people, and here’s all the source code if you would like to check as well:</p><p><a href="https://github.com/deda9/CoreData-Combine">deda9/CoreData-Combine</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c80373c5484" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/ios-core-data-with-combine-c80373c5484">iOS Core Data With Combine</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[iOS Core Data with Sugar Syntax]]></title>
            <link>https://blog.devgenius.io/ios-core-data-with-sugar-syntax-ef53a0e06efe?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/ef53a0e06efe</guid>
            <category><![CDATA[core-data]]></category>
            <category><![CDATA[sugar]]></category>
            <category><![CDATA[sqlite]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Thu, 19 Nov 2020 13:38:02 GMT</pubDate>
            <atom:updated>2020-11-28T22:57:18.472Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Let7RsfLQHYbv64o" /><figcaption>Photo by <a href="https://unsplash.com/@jankolar?utm_source=medium&amp;utm_medium=referral">Jan Antonin Kolar</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>When I started iOS programming since years ago I was mixing up between the Core Data and the Database, but in fact the Core Data is not a database even Core Data is actually backed by an SQLite database but both of them are ways of providing searchable and persistent storage. In short description we can say that SQLite is a database itself and Core Data is an ORM (Object Relational Model) which creates a layer between the database and the UI.</p><h3>What’s Core Data?</h3><p>Core Data is a framework that you use to manage <strong>the model layer objects</strong> in your application. It provides generalized and automated solutions to common tasks associated with object life cycle and object graph management, including persistence. It typically decreases by <strong>50</strong> to <strong>70</strong> percent the amount of code you write to support the model layer and to well understand the Core data and how it works we need to understand the <em>Core Data Stack</em>.</p><h3>What’s Core Data Stack?</h3><p>The <em>Core Data stack</em> is a collection of framework objects that are accessed as part of the initialization of Core Data and that mediate between the objects in your application and external data stores. The Core Data stack handles all of the interactions with the external data stores so that your application can focus on its business logic. The stack consists of <strong><em>four primary</em></strong> objects:</p><figure><img alt="https://docs-assets.developer.apple.com/published/af070d78c7/73827830-1e19-4865-8757-c4d9f8ccacfb.png" src="https://cdn-images-1.medium.com/max/1024/1*mJfF39Zz2IHl4BlZz9nPgQ.png" /><figcaption><a href="https://docs-assets.developer.apple.com/published/af070d78c7/73827830-1e19-4865-8757-c4d9f8ccacfb.png">https://docs-assets.developer.apple.com/published/af070d78c7/73827830-1e19-4865-8757-c4d9f8ccacfb.png</a></figcaption></figure><ul><li><a href="https://developer.apple.com/documentation/coredata/nspersistentcontainer"><em>NSPersistentContainer</em></a> handles the creation of the Core Data stack and offers access to the NSManagedObjectContext as well as a number of convenience methods.</li><li><a href="https://developer.apple.com/documentation/coredata/nsmanagedobjectmodel"><em>NSManagedObjectModel</em></a> describes the data that is going to be accessed by the Core Data stack. During the creation of the Core Data stack, the NSManagedObjectModel is loaded into memory as the first step in the creation of the stack. After the NSManagedObjectModel object is initialized, the NSPersistentStoreCoordinator object is constructed.</li><li><a href="https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext"><em>NSManagedObjectContext</em></a> is the object that your application will interact with the most. Think of it as an intelligent scratch pad. When you fetch objects from a persistent store, you bring temporary copies onto the scratch pad where they form an object graph. You can then modify those objects however you like and if you choose to save the changes you have made, the context ensures that your objects are in a valid state. If they are, the changes are written to the persistent store, new records are added for objects you created, and records are removed for objects you deleted.</li><li><a href="https://developer.apple.com/documentation/coredata/nspersistentstorecoordinator"><em>NSPersistentStoreCoordinator</em></a> sits in the middle of the Core Data stack. It is responsible for realizing instances of entities that are defined inside of the model. It creates new instances of the entities in the model, and it retrieves existing instances from a persistent store (<a href="https://developer.apple.com/documentation/coredata/nspersistentstore">NSPersistentStore</a>) which can be on disk or in memory depending on the structure of the application.</li></ul><h3>1- Initializing the Core Data Stack</h3><ul><li>The initialization of the stack prepares Core Data for data requests and the creation of data.</li><li>Starting in <em>iOS 10</em> the NSPersistentContainer handles the creation of the Core Data stack but prior to iOS 10 the creation of the Core Data stack was more involved and <a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/InitializingtheCoreDataStack.html#//apple_ref/doc/uid/TP40001075-CH4-SW1"><em>you can read more</em></a>.</li><li>Here’s an example of how to create that Core Data stack:</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f7c0c555f27068b672baa39a13d1e899/href">https://medium.com/media/f7c0c555f27068b672baa39a13d1e899/href</a></iframe><h3>2- Creating a Managed Object Model</h3><ul><li>Much of Core Data’s functionality depends on the <strong><em>schema</em></strong> you create to describe your application’s entities, their properties, and the relationships between them. Core Data uses a schema called a <em>managed object model</em> an instance of <a href="https://developer.apple.com/documentation/coredata/nsmanagedobjectmodel">NSManagedObjectModel</a>.</li><li>Image that we have an entity is called Person who has first_name and last_name and owns a car then the Car will be another entity which has a name and the owner attributes.</li><li>The <em>owner</em> might have more than one <em>car</em> then we will create <em>one-to-many</em> relationship between the owner and the car.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E9K3mxz_flSeucDl83fqUw.png" /></figure><p>1- Click on Add Entity button and create the <strong>Person</strong> and <strong>Car</strong> entities.<br>2- Create the <strong>first_name</strong> and <strong>last_name</strong> attributes for the Person entity.<br>3- Create the relationship between the owner and the car.<br>4- Make the relationship <strong>one-to-many</strong>.<br>5- Do the same for the <strong>Car</strong> entity.</p><h3>3- Creating Managed Objects</h3><ul><li>After you have defined your managed object model and initialized the Core Data stack within your application, you are ready to start creating objects for data storage.</li><li>I’ve created some sugar syntax to create entities and save them and you can check the complete source code at the end of the article.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2198bd9fdda9c57b790881af0444290b/href">https://medium.com/media/2198bd9fdda9c57b790881af0444290b/href</a></iframe><h3>4- Saving Managed Objects</h3><ul><li>After creating the entities and their attributes all we need is to call save or saveSync to explicitly save that context to persist those changes to your persistent store.</li></ul><h3>5- Fetching Objects</h3><ul><li>Now that data is stored in the Core Data persistent store, you will use an <a href="https://developer.apple.com/documentation/coredata/nsfetchrequest">NSFetchRequest</a> to access that existing data.</li><li>You start by constructing an NSFetchRequest that describes the data you want returned.</li><li>You then call <a href="https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext/1506672-fetch">fetch(:</a>) on the <a href="https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext">NSManagedObjectContext</a> and pass in the request.</li><li>I’ve added some sugar syntax to make our life easy and just call fetch.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/136f60fe559f8345a8d44f16cccadb47/href">https://medium.com/media/136f60fe559f8345a8d44f16cccadb47/href</a></iframe><h3>6- Deleting Entities from CoreData</h3><ul><li>Actually it’s so simple to delete any entity from the Core Data. It only requires to pass NSFetchRequest instance and after that we execute the batch delete request on your managed object context.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/04f56767049975dc947c9e72b5a5c1a4/href">https://medium.com/media/04f56767049975dc947c9e72b5a5c1a4/href</a></iframe><h3>7- Using Core Data in the Background</h3><ul><li>Core Data is designed to work in a multithreaded environment.</li><li>Managed object contexts are bound to the thread that they are associated with upon initialization.</li><li>Managed objects retrieved from a context are bound to the same queue that the context is bound to.</li><li>There are two types of managed object contexts: <strong>main queue</strong> and <strong>private queue</strong>.</li><li>Here’s an example how we can use a private queue to support concurrency</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6df923f07efb3b392f05081d3af45aad/href">https://medium.com/media/6df923f07efb3b392f05081d3af45aad/href</a></iframe><ul><li>We created a new NSManagedObjectContext that is defined as a private queue and the new context is set as a child of the main queue context that runs the application then call performBlock: to do the actual work and after all of the data has been consumed, you call save on the private context, which moves all of the changes into the main queue context without blocking the main queue.</li></ul><h3>8- Performance tips</h3><ul><li>Each round trip to the persistent store incurs an overhead, both in accessing the store and in merging the returned objects into the persistence stack. Avoid executing multiple requests if you can instead combine them into a single request that will return all the objects you require.</li><li>If a fetch request requires a compound predicate, you can make the fetch more efficient by ensuring that the most restrictive predicate is the first, especially if the predicate involves text matching (contains, endsWith, like, and matches).</li><li>You can set a limit to the number of objects a fetch will return to minimize the working set of managed objects in memory and so improve the performance of your application.</li><li>Use Prefetching and the idea behind prefetching is the anticipation of future needs. When you fetch some objects, sometimes you know that soon after you will also need related objects which may be represented by faults.</li><li>Avoid using Core Data as a store for large blocks of binary data, such as videos, images, or audio.</li><li>Avoid blocking the main thread of your application by using background threading and switching to the main queue to update the user interface.</li></ul><h4><strong>Here’s all the complete sugar syntax</strong></h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/252bc2f4d1d7b2293f42b51fe6bb07cf/href">https://medium.com/media/252bc2f4d1d7b2293f42b51fe6bb07cf/href</a></iframe><p>Hope you enjoyed as I did 😃🎉 and if so feel free to clap and if you liked more feel free to clap more 😃 and share with your friends, Its always pleasure to share with people, and here’s all the source code if you would like to check as well:</p><p><a href="https://github.com/deda9/CoreDataExample">deda9/CoreDataExample</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ef53a0e06efe" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/ios-core-data-with-sugar-syntax-ef53a0e06efe">iOS Core Data with Sugar Syntax</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Learn Combine by code Series (Part 3)]]></title>
            <link>https://blog.devgenius.io/learn-combine-by-code-series-part-3-c9b857c837eb?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/c9b857c837eb</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[combine]]></category>
            <category><![CDATA[reactive-programming]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swiftui]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Sat, 31 Oct 2020 00:14:48 GMT</pubDate>
            <atom:updated>2020-11-28T22:57:50.557Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*90zE-0U55ZntISkb" /><figcaption>Photo by <a href="https://unsplash.com/@max_duz?utm_source=medium&amp;utm_medium=referral">Max Duzij</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>In <a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c">Part 1</a> talked about what’s Combine and how we can understand and use it and in <a href="https://deda9.medium.com/learn-combine-by-code-series-part-2-aa7083bad99e">Part 2</a> talked about more examples of the usage.</p><p>Now let’s leverage what we have learned and apply into real examples.</p><h4>1- Listen to UITextField when text did change</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/536dc361f913b49a6014653029d42d66/href">https://medium.com/media/536dc361f913b49a6014653029d42d66/href</a></iframe><h4>2- Check if the device orientation is portrait</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b94b1e32edb62fb64d61aad156576697/href">https://medium.com/media/b94b1e32edb62fb64d61aad156576697/href</a></iframe><h4>3- Execute network request when user types any text on UITextField</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/257c74147cb3ec170d0f22b8f0f68bf4/href">https://medium.com/media/257c74147cb3ec170d0f22b8f0f68bf4/href</a></iframe><ul><li>You can read more about <a href="https://medium.com/dev-genius/learn-combine-by-code-series-part-2-aa7083bad99e#f90e">Debounce</a>, <a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c#6b64">CompactMap</a>, <a href="https://medium.com/dev-genius/learn-combine-by-code-series-part-2-aa7083bad99e#76b5">RemoveDuplicates</a>, <a href="https://medium.com/dev-genius/learn-combine-by-code-series-part-2-aa7083bad99e#cda2">FlatMap</a> and <a href="https://medium.com/dev-genius/learn-combine-by-code-series-part-2-aa7083bad99e#9de0">ReceiveOn</a>.</li></ul><h4>4- Performing Key-Value Observing to listen to a property’s value change</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9974080e7593ebaca6263fb838e06c96/href">https://medium.com/media/9974080e7593ebaca6263fb838e06c96/href</a></iframe><ul><li>The User class should beNSObject and the property should be@objc dynamic.</li></ul><h4>5- Create a Timer</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/934b56b0e3531bca3b3d3575cbf7b486/href">https://medium.com/media/934b56b0e3531bca3b3d3575cbf7b486/href</a></iframe><ul><li>You can read more about <a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c#d29e">AutoConnect</a> and <a href="https://medium.com/dev-genius/learn-combine-by-code-series-part-2-aa7083bad99e#9de0">ReceiveOn</a>.</li></ul><h4>6- Credentials validation to enable login button</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c9c6736625c16f645db8c7f3c442ced2/href">https://medium.com/media/c9c6736625c16f645db8c7f3c442ced2/href</a></iframe><ul><li>You can read more about <a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c#dadd">CombineLatest</a> and <a href="https://medium.com/dev-genius/learn-combine-by-code-series-part-2-aa7083bad99e#ee81">Share</a></li></ul><h4>7- Ask the user for the notification permission</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d190ec60ed177cbc0d9cd5e0c207a643/href">https://medium.com/media/d190ec60ed177cbc0d9cd5e0c207a643/href</a></iframe><ul><li>You can read more about <a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c#4f69">Future</a> and <a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c#bc8d">Catch</a></li><li>Its always good to breakdown the code into small functions, otherwise it will be ended up with a huge chain and that’s one of the drawback of reactive programming.</li></ul><h4>8- Execute URLSession request</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/378b80a15f8eb5bd13248ca37db43074/href">https://medium.com/media/378b80a15f8eb5bd13248ca37db43074/href</a></iframe><h4>9- Execute two URLSession requests and wait for their results when they are finished</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7fd0424f923802493085d64f1daf5d5d/href">https://medium.com/media/7fd0424f923802493085d64f1daf5d5d/href</a></iframe><h4>10- Trace user location when it changed</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/18c1fda20747bfae0b47f414ef3a6c40/href">https://medium.com/media/18c1fda20747bfae0b47f414ef3a6c40/href</a></iframe><p>Hope you enjoyed as I did 😃🎉 and if so feel free to clap and if you liked more feel free to clap more 😃 and share with your friends, Its always pleasure to share with people.</p><p>Don’t forget to check the other pars of the series 🚀</p><ul><li><a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c">Learn Combine by code Series (Part 1)</a></li><li><a href="https://medium.com/dev-genius/learn-combine-by-code-series-part-2-aa7083bad99e">Learn Combine by code Series (Part 2)</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c9b857c837eb" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/learn-combine-by-code-series-part-3-c9b857c837eb">Learn Combine by code Series (Part 3)</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Learn Combine by code Series (Part 2)]]></title>
            <link>https://blog.devgenius.io/learn-combine-by-code-series-part-2-aa7083bad99e?source=rss-43616b42e912------2</link>
            <guid isPermaLink="false">https://medium.com/p/aa7083bad99e</guid>
            <category><![CDATA[combine]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[reactive-programming]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Bassem Qoulta]]></dc:creator>
            <pubDate>Wed, 28 Oct 2020 20:40:23 GMT</pubDate>
            <atom:updated>2020-11-28T22:58:21.960Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OkUV2vBdF0UzMtBV" /><figcaption>Photo by <a href="https://unsplash.com/@max_duz?utm_source=medium&amp;utm_medium=referral">Max Duzij</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>In <a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c">Part 1</a> talked about what’s Combine and how we can understand and use it and in this part will go continuing the examples of the usage.</p><h4>16- Comparison</h4><ul><li>When we need to republish items from another publisher only if each new item is in increasing order from the previously-published item.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7b54fde7b2a1470523972b0a9cfa862a/href">https://medium.com/media/7b54fde7b2a1470523972b0a9cfa862a/href</a></iframe><pre>a is: 1 b is: 4<br>a is: 2 b is: 4<br>a is: 0 b is: 4<br>a is: 3 b is: 4</pre><pre>Value is: 4</pre><h4>17- Concatenate</h4><ul><li>When we need to emit all of one publisher’s elements before those from another publisher.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5e7ff581ef71614443c5566c4f0a7a58/href">https://medium.com/media/5e7ff581ef71614443c5566c4f0a7a58/href</a></iframe><pre>Value is: A1<br>Value is: A2<br>Value is: B1<br>Value is: B2</pre><h4>18- Contains</h4><ul><li>When we need to emit a Boolean value when a specified element is received from its upstream publisher.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ddcd2e74d612563820a879b1eec51b5e/href">https://medium.com/media/ddcd2e74d612563820a879b1eec51b5e/href</a></iframe><pre>Does numbers contains A1?  true</pre><h4>19- ContainsWhere</h4><ul><li>When we need to emits a Boolean value upon receiving an element that satisfies the predicate closure.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7819bff28a6998708f703e5f1dad2026/href">https://medium.com/media/7819bff28a6998708f703e5f1dad2026/href</a></iframe><pre>Does numbers contains A?:  true</pre><h4>20- Count</h4><ul><li>When we need to publish the number of elements received from the upstream publisher.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/24201016b517a22d2eab357ff06fa1ce/href">https://medium.com/media/24201016b517a22d2eab357ff06fa1ce/href</a></iframe><pre>Count of numbers publisher is: 3</pre><h4>21- Debounce</h4><ul><li>When we need to publish elements only after a specified time interval elapses between events.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5d6efbe4927f85e92eab56a3d6c406a0/href">https://medium.com/media/5d6efbe4927f85e92eab56a3d6c406a0/href</a></iframe><pre>Time now is:  <strong>2020-10-25 19:20:25 +0000</strong><br>value is: <strong>AA</strong> at time:  <strong>2020-10-25 19:20:27 +0000</strong></pre><h4>22- Delay</h4><ul><li>When we need to delay the delivery of the elements and the completion to the downstream receiver.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2a437dce6313165aa1405d33e02a92b1/href">https://medium.com/media/2a437dce6313165aa1405d33e02a92b1/href</a></iframe><pre>Time now is:  2020-10-26 <strong>22:43:26</strong> +0000<br>value: is 1 at time:  2020-10-26 <strong>22:43:36</strong> +0000<br>value: is 2 at time:  2020-10-26 <strong>22:43:36</strong> +0000<br>value: is 3 at time:  2020-10-26 <strong>22:43:36</strong> +0000<br>Finished at time:  2020-10-26 <strong>22:43:36</strong> +0000</pre><h4>23- Drop</h4><ul><li>When we need to omit a specified number of elements before republishing later elements.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e55414f82544e0917b0005ae66c2a090/href">https://medium.com/media/e55414f82544e0917b0005ae66c2a090/href</a></iframe><h4>24- DropUntilOutput</h4><ul><li>When we need to ignore elements from the upstream publisher until it receives an element from second publisher.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/59b5da71cecf27b1b257937b4f3dde9f/href">https://medium.com/media/59b5da71cecf27b1b257937b4f3dde9f/href</a></iframe><pre>value is:  A3<br>value is:  A4</pre><h4>25- DropWhile</h4><ul><li>When we need to omit elements from an upstream publisher until a given closure returns false.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/51037e8816fb1a95f3d4650240fba4f9/href">https://medium.com/media/51037e8816fb1a95f3d4650240fba4f9/href</a></iframe><pre>value is:  B1<br>value is:  B2</pre><h4>26- Filter</h4><ul><li>When we need to republish all elements that match a provided closure.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5f463940dd4e9bae5bffad68e08fa1a0/href">https://medium.com/media/5f463940dd4e9bae5bffad68e08fa1a0/href</a></iframe><pre>value is:  A1<br>value is:  A2</pre><h4>27- First</h4><ul><li>When we need to publish the first element of a stream, then finishes.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1adfaeb6444e5822eb39aae0c3d99d1d/href">https://medium.com/media/1adfaeb6444e5822eb39aae0c3d99d1d/href</a></iframe><pre>value is:  A1</pre><h4>28- FirstWhere</h4><ul><li>When we need only to publish the first element of a stream to satisfy a predicate closure.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c9829cca9100f88158e046cdd6a7828f/href">https://medium.com/media/c9829cca9100f88158e046cdd6a7828f/href</a></iframe><pre>value is:  A1</pre><h4>29- FlatMap</h4><ul><li>When we need to transform elements from an upstream publisher into a new publisher.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dd1b66c4e065f091660741d81c6ba044/href">https://medium.com/media/dd1b66c4e065f091660741d81c6ba044/href</a></iframe><pre>value is:  2<br>value is:  4<br>value is:  6</pre><h4>30- HandleEvents</h4><ul><li>When we need to perform the specified closures when publisher events occur.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0ec5e1f37e33c5683de099e2a75600f1/href">https://medium.com/media/0ec5e1f37e33c5683de099e2a75600f1/href</a></iframe><pre>receiveSubscription [1, 2, 3]<br>receiveRequest demand unlimited<br>receiveOutput 1<br>value is:  1<br>receiveOutput 2<br>value is:  2<br>receiveOutput 3<br>value is:  3<br>receiveCompletion finished</pre><h4>31- IgnoreOutput</h4><ul><li>When we need to ignore all upstream elements, but passes along a completion state (finish or failed).</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/321305710fee3f408a1fad137def59d4/href">https://medium.com/media/321305710fee3f408a1fad137def59d4/href</a></iframe><pre>receiveCompletion finished</pre><h4>32- Last</h4><ul><li>When we need only to publish the last element of a stream, after the stream finishes.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2fd9272c420cee7e350d6287fe2aa0f4/href">https://medium.com/media/2fd9272c420cee7e350d6287fe2aa0f4/href</a></iframe><pre>value is:  3</pre><h4>33- LastWhere</h4><ul><li>When we need only to publish the last element of a stream that satisfies a predicate closure, once the stream finishes.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/259dcd4d30bc56022e1739bf520a98a9/href">https://medium.com/media/259dcd4d30bc56022e1739bf520a98a9/href</a></iframe><pre>value is:  3</pre><h4>34- MakeConnectable</h4><ul><li>When we need to provide explicit connectability to another publisher.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/56725f87d3cae1e22bb7c3e748c48d92/href">https://medium.com/media/56725f87d3cae1e22bb7c3e748c48d92/href</a></iframe><pre>value is:  B1</pre><h4>35- Map</h4><ul><li>When we need to transform all elements from the upstream publisher with a provided closure.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b6baaa1906d41ae1c7f6b2ac9e75330b/href">https://medium.com/media/b6baaa1906d41ae1c7f6b2ac9e75330b/href</a></iframe><pre>value is:  A1<br>value is:  A2<br>value is:  A3</pre><h4>36- Merge</h4><ul><li>When we need applying the merge function to two upstream publishers</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2d37daafa8503ea546d7219ebdc3e8a2/href">https://medium.com/media/2d37daafa8503ea546d7219ebdc3e8a2/href</a></iframe><pre>value is:  1<br>value is:  2<br>value is:  3<br>value is:  4<br>value is:  5<br>value is:  6</pre><h4>37- Multicast</h4><ul><li>When we need to use a subject to deliver elements to multiple subscribers.</li><li>It returns a ConnectablePublisher which publishing only begins after a call to connect().</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/91a99b8bf38e44afb18813cf2a9eb002/href">https://medium.com/media/91a99b8bf38e44afb18813cf2a9eb002/href</a></iframe><pre>Stream 1 received: First<br>Stream 1 received: Second<br>Stream 1 received: Third<br>Stream 2 received: First<br>Stream 2 received: Second<br>Stream 2 received: Third</pre><h4>38- ReceiveOn</h4><ul><li>When we need to deliver elements to its downstream subscriber on a specific scheduler.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/efbc6618400954b0a4e2ddf2c6605542/href">https://medium.com/media/efbc6618400954b0a4e2ddf2c6605542/href</a></iframe><pre>value is:  First<br>value is:  Second<br>value is:  Third</pre><h4>39- RemoveDuplicates</h4><ul><li>When we need to publish only elements that don’t match the previous element.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/abfd1bdd128f00c9a4327499e860f478/href">https://medium.com/media/abfd1bdd128f00c9a4327499e860f478/href</a></iframe><pre>value is:  First<br>value is:  Third</pre><h4>40- Reduce</h4><ul><li>When we need to apply a closure to all received elements and produces an accumulated value when the upstream publisher finishes.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a3030484788226138c7ccc0f03a67b94/href">https://medium.com/media/a3030484788226138c7ccc0f03a67b94/href</a></iframe><pre>55 finished</pre><h4>41- Scan</h4><ul><li>When we need to accumulate all previously-published values into a single value, which you then combine with each newly-published value.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/abdfc40f71f0e6eac2531555d0a2a3d3/href">https://medium.com/media/abdfc40f71f0e6eac2531555d0a2a3d3/href</a></iframe><pre>0 1 3 6 10 15</pre><h4>42- Share</h4><ul><li>When we need to share the output of an upstream publisher with multiple subscribers.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/483563f3788c2013699f332654a7286d/href">https://medium.com/media/483563f3788c2013699f332654a7286d/href</a></iframe><pre>Random: receive subscription: ([55, 69, 38])<br>Random: request unlimited<br>Random: receive value: (55)<br>Stream 1 received: 55<br>Random: receive value: (69)<br>Stream 1 received: 69<br>Random: receive value: (38)<br>Stream 1 received: 38<br>Random: receive finished</pre><h4>43- SubscribeOn</h4><ul><li>When we need to receive elements from an upstream publisher on a specific scheduler.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8bcdd81e896dde40a6ebbfc42d7ebdd2/href">https://medium.com/media/8bcdd81e896dde40a6ebbfc42d7ebdd2/href</a></iframe><pre>Stream received: 1<br>Stream received: 2<br>Stream received: 3</pre><h4>44- SwitchToLatest</h4><ul><li>When we need to produce a sequence of events from only the most recent one.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2be2b46ba4a19d0d03f1bb3232a77ab1/href">https://medium.com/media/2be2b46ba4a19d0d03f1bb3232a77ab1/href</a></iframe><pre>URL: https://example.org/get?index=5</pre><h4>45- Throttle</h4><ul><li>When we need to selectively republish elements from an upstream publisher during an interval you specify.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6b20af307e9369f079b93a9e0770fd31/href">https://medium.com/media/6b20af307e9369f079b93a9e0770fd31/href</a></iframe><pre><strong>Received Timestamp 2020-10-28 20:24:17 +0000</strong><br>receive value: (2020-10-28 20:24:18 +0000)<br>receive value: (2020-10-28 20:24:19 +0000)<br>receive value: (2020-10-28 20:24:20 +0000)<br><strong>Received Timestamp 2020-10-28 20:24:20 +0000</strong><br>receive value: (2020-10-28 20:24:21 +0000)<br>receive value: (2020-10-28 20:24:22 +0000)<br>receive value: (2020-10-28 20:24:23 +0000)<br><strong>Received Timestamp 2020-10-28 20:24:23 +0000</strong></pre><h4>46- Zip</h4><ul><li>When we need to combine the latest elements from two publishers and emit a tuple to the downstream.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2085f5a0c72e6663c2c1b94755adac4a/href">https://medium.com/media/2085f5a0c72e6663c2c1b94755adac4a/href</a></iframe><pre>(1, &quot;A&quot;)<br>(2, &quot;B&quot;)</pre><h4>47- TryCatch</h4><ul><li>When we need to decide how to handle from an upstream publisher by either replacing the publisher with a new publisher, or throwing a new error.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/25589c595c658a84c9dbf2ee0e55f7ff/href">https://medium.com/media/25589c595c658a84c9dbf2ee0e55f7ff/href</a></iframe><pre>Received 5.<br>Received 4.<br>Received 3.<br>Received 2.<br>Received 1.<br>Received 0.<br>Completion: finished.</pre><h4>48- Timeout</h4><ul><li>When we need to terminate a publisher if an element isn’t delivered within a timeout interval you specify.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/acabfbf29f00b368c5acf5cb82dd7fc1/href">https://medium.com/media/acabfbf29f00b368c5acf5cb82dd7fc1/href</a></iframe><pre>completion: finished at 2020-10-28 20:34:54 +0000</pre><p>I really do love the reactive programming and enjoying learning it. Hope you enjoyed as I did 😃🎉 and if so feel free to clap and if you liked more feel free to clap more 😃 and share with your friends, Its always pleasure to share with people.</p><p>Don’t forget to check the other parts of the series 🚀</p><ul><li><a href="https://medium.com/dev-genius/learn-combine-by-code-55e661a5256c">Learn Combine by code Series (Part 1)</a></li><li><a href="https://deda9.medium.com/learn-combine-by-code-series-part-3-c9b857c837eb">Learn Combine by code Series (Part 3)</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aa7083bad99e" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/learn-combine-by-code-series-part-2-aa7083bad99e">Learn Combine by code Series (Part 2)</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>