<?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 Rishabh Sharma on Medium]]></title>
        <description><![CDATA[Stories by Rishabh Sharma on Medium]]></description>
        <link>https://medium.com/@rishixcode?source=rss-f86c9c34c98e------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*ReobLRvAtV7vRe4ux0pL-w.jpeg</url>
            <title>Stories by Rishabh Sharma on Medium</title>
            <link>https://medium.com/@rishixcode?source=rss-f86c9c34c98e------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 31 May 2026 11:37:25 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@rishixcode/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[Interview Experience for SDE-II iOS at Swiggy ]]></title>
            <link>https://medium.com/@rishixcode/interview-experience-for-sde-ii-ios-at-swiggy-d95a3c244f56?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/d95a3c244f56</guid>
            <category><![CDATA[interview]]></category>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[swiggy]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Thu, 22 May 2025 14:12:36 GMT</pubDate>
            <atom:updated>2025-05-22T14:12:36.700Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OB5dFtKuqbbFbXwWv7nlEQ.png" /></figure><p>Hey everyone! 👋<br>I recently interviewed for the <strong>SDE-2 iOS role at Swiggy</strong>, and I wanted to share my journey with all of you. The process was <strong>structured into 4 rounds</strong>, and it covered everything from <strong>Swift basics and concurrency</strong> to <strong>system design and SwiftUI</strong>.</p><p>If you’re preparing for similar interviews, I hope this blog helps you understand what to expect and how to prepare better!</p><h3>🧠 Round 1: Online Assessment (OA)</h3><p>This was a timed online test that had a mix of <strong>DSA</strong>, <strong>Swift-specific MCQs</strong>, and <strong>SwiftUI-based snippet questions</strong>.</p><p>🧩 <strong>Problems I faced:</strong></p><ul><li><strong>Roman to Integer</strong></li><li>A <strong>Graph Problem (Medium-Hard)</strong> — Took some time, but I managed a working solution</li><li><strong>Swift MCQs</strong> — Focused on closures, optionals, memory handling</li><li><strong>SwiftUI Snippet MCQs</strong> — A few questions around @State, @Binding, @ObservedObject, and UI behavior</li></ul><p>This round was a <strong>good mix of theory and implementation</strong>, and a clear test of your understanding of <strong>Swift and SwiftUI fundamentals</strong>.</p><h3>🍏 Round 2: iOS Deep Dive (Part 1)</h3><p>This was a <strong>very technical round focused on Swift and iOS internals.</strong></p><h3>🔐 Task:</h3><blockquote><em>Create a thread-safe singleton class named </em><em>ThreadSafeDataStorage in Swift, with </em><em>readData() and </em><em>writeData(_:) methods.</em></blockquote><p>The catch was to <strong>ensure thread-safety using DispatchQueue</strong> and handle <strong>concurrent access</strong> properly.</p><p>Other topics discussed:</p><ul><li><strong>Retain cycles</strong> and how to resolve them</li><li>Create a <strong>custom optional type</strong> and write logic similar to if let</li><li>General iOS questions</li><li>A custom implementation of map(_:)</li></ul><p>This round required <strong>clarity of core concepts</strong> and <strong>Swift syntax fluency</strong>.</p><h3>🧱 Round 3: System Design — Swiggy Order Tracking Screen</h3><p>This round was all about <strong>high-level design</strong>, not just from an architecture perspective but also <strong>user experience</strong>.</p><h3>🎯 Problem:</h3><blockquote><em>Design the “Track My Order” screen from Swiggy</em></blockquote><p>💡 What I covered:</p><ul><li>Live status updates</li><li>API design for status changes</li><li>Real-time updates using sockets or polling</li><li>Dynamic UI updates as per state (order confirmed, picked, delivered)</li><li><strong>Data models</strong> and how they’d look in Swift</li><li>Basic <strong>HLD</strong> components and flow</li></ul><p>It was an <strong>open-ended round</strong>, and the discussion was both technical and product-focused.</p><h3>🍎 Round 4: iOS Deep Dive (Part 2)</h3><p>This round felt more like a <strong>deep technical audit</strong> of how I think about iOS development.</p><p>🧠 Topics included:</p><ul><li><strong>ARC and memory management</strong></li><li><strong>GCD</strong> — DispatchBarrier, concurrent reads, serial writes</li><li><strong>Closures and retain cycles</strong></li><li><strong>MVVM architecture</strong> — Real-world usage</li><li><strong>Singletons &amp; thread safety</strong></li><li><strong>Communication patterns</strong> — Delegate, NotificationCenter, Combine</li><li><strong>Copy-on-write</strong> — How it works, when it triggers</li><li><strong>Weak vs Unowned</strong> — Rules and use-cases</li><li><strong>App size optimization</strong> — What steps I follow</li><li>What I’ve worked on personally</li><li><strong>SwiftUI</strong> — Understanding of @State, @Binding, @Environment, @ObservedObject</li><li>SwiftUI benefits and when <strong>to avoid it</strong></li><li>Writing and structuring <strong>custom reusable views</strong></li></ul><p>This was probably my favorite round. It was a <strong>healthy mix of theory, practical knowledge, and architectural thinking</strong>.</p><h3>🔚 Final Thoughts</h3><p>The Swiggy interview process was <strong>very well-structured</strong> and pushed me to think deeper about my day-to-day development habits.</p><p>If you’re preparing:</p><ul><li>Brush up on <strong>Swift and iOS fundamentals</strong></li><li>Practice <strong>thread-safe coding patterns</strong></li><li>Be comfortable with <strong>SwiftUI and its property wrappers</strong></li><li>Understand real-world <strong>system design in mobile apps</strong></li></ul><p>Hope this blog helps you in your journey. If you have any questions or want to discuss interview prep, feel free to drop a comment or connect with me! 😊</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d95a3c244f56" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Interview Experience for SDE-II iOS at Flipkart]]></title>
            <link>https://medium.com/@rishixcode/interview-experience-for-sde-ii-ios-at-flipkart-ac6b8f865647?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/ac6b8f865647</guid>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[jobs]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[interview]]></category>
            <category><![CDATA[flipkart]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Mon, 17 Mar 2025 13:14:48 GMT</pubDate>
            <atom:updated>2025-03-17T13:14:48.582Z</atom:updated>
            <content:encoded><![CDATA[<h4>Hey everyone! 👋 I recently went through the interview process for <strong>SDE-2 iOS at Flipkart</strong>, and I wanted to share my experience. Most of the resources I found online mentioned <strong>4 rounds</strong>, but I had <strong>5 rounds</strong>, which was a bit surprising. Here’s a breakdown of what happened in each round and the types of questions I faced.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nJagRbVx4PYkrGnTxBFBPg.png" /></figure><h3>Round 1: Machine Coding 💻</h3><p>This was a hands-on round where I had to <strong>write working code</strong> for a given problem. The main focus was on logic, correctness, and clean code. The problem statement required structuring the solution efficiently.</p><h3>Round 2: DSA 🔢</h3><p>This round focused on <strong>Data Structures &amp; Algorithms</strong>. I solved:</p><p>1️⃣ <strong>Graph Question</strong> — <a href="https://leetcode.com/problems/number-of-islands/">Number of Islands</a> 🏝️</p><ul><li>Standard DFS/BFS problem. Since I had practiced similar problems before, I managed to solve it.</li></ul><p>2️⃣ <strong>Two Pointers / Array Question</strong> — <a href="https://leetcode.com/problems/container-with-most-water/">Container With Most Water</a> 🛢️</p><ul><li>This was also straightforward, and I solved it using the <strong>two-pointer approach</strong>.</li></ul><p>3️⃣ <strong>Modified Version of Above Problem</strong> — ❌ <strong>Couldn’t solve this one</strong></p><ul><li>The interviewer modified the second question, making it trickier. I tried a few approaches but couldn’t get to the optimal solution.</li></ul><h3>Round 3: iOS Deep Dive 🍏</h3><p>This round was heavily focused on <strong>iOS internals</strong> and Swift fundamentals.</p><p>✅ <strong>Value vs Reference Types</strong><br>✅ <strong>Structs in Detail</strong><br>✅ <strong>Memory Management</strong><br>✅ <strong>Memory Address in Structs</strong></p><p>A really interesting discussion happened around <strong>memory addresses in structures</strong>:</p><pre>struct Example {<br>    var a: Int<br>}<br><br>var struct1 = Example(a: 5)<br>var struct2 = struct1<br>struct2.a = 9</pre><p><strong>Will the memory address of </strong><strong>a change?</strong> 🤔</p><p>Then we went deeper into <strong>Copy-on-Write</strong> and why <strong>only arrays and dictionaries</strong> use it natively but not structs.</p><p>Another tricky question: <strong>If a struct has an array and we copy the struct, will the array still have the same address?</strong></p><p>Other topics:<br>✅ <strong>Retain Cycles &amp; ARC</strong><br>✅ <strong>How retain cycles are formed</strong> (Examples)<br>✅ <strong>How to resolve them (Weak vs Unowned)</strong></p><h3>Round 4: System Design 🎮</h3><p>This was quite <strong>different from a typical iOS System Design round</strong>. Instead of asking me to design an app or API, the problem was:</p><p>💣 <strong>Design a Matrix Game</strong></p><ul><li>Players can <strong>bomb opponent’s mines</strong></li><li>The person who bombs <strong>all mines wins</strong></li><li><strong>No need to discuss scope/features, just focus on game logic</strong></li></ul><p>It was a fun and challenging problem that required <strong>thinking through state changes and efficient updates</strong>.</p><h3>Round 5: Hiring Manager 🧑‍💼 (The Toughest!)</h3><p>This was the <strong>most difficult</strong> and detailed round. The HM went deep into my <strong>resume and past projects</strong>.</p><p>🚀 <strong>Topics Discussed:</strong><br>✔️ <strong>WebSockets</strong> — How I used them in a project<br>✔️ <strong>Maps &amp; Heatmaps</strong> — How I implemented them in an app<br>✔️ <strong>Audio/Video Streaming</strong> — Why quality drops on bad networks<br>✔️ <strong>App Performance</strong> — How to <strong>improve load times</strong><br>✔️ <strong>Payment Gateway (Stripe)</strong> — What happens when a <strong>payment fails</strong>?<br>✔️ <strong>Beta Testing &amp; CI/CD</strong><br>✔️ <strong>Authentication Flows</strong> — Handling logins securely<br>✔️ <strong>Storing Images in AWS</strong> — Managing <strong>multiple resolutions</strong></p><h3>Final Thoughts 🤔</h3><p>Overall, it was a <strong>challenging yet rewarding</strong> experience. Flipkart’s interview process <strong>tests both DSA and deep iOS knowledge</strong>. If you’re preparing:</p><p>✅ <strong>Brush up on DSA (especially graphs, arrays, and modifications of known problems)</strong><br>✅ <strong>Deep dive into Swift internals (memory management, retain cycles, ARC, copy-on-write)</strong><br>✅ <strong>Prepare to discuss real-world projects in detail</strong><br>✅ <strong>Be ready for System Design (can be unconventional like mine!)</strong></p><p>Hope this helps anyone preparing for <strong>Flipkart SDE-2 iOS</strong>! Feel free to drop any questions below. 🚀</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ac6b8f865647" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Interview Experience for SDE-III iOS at Walmart]]></title>
            <link>https://medium.com/@rishixcode/interview-experience-for-sde-iii-ios-at-walmart-9ab411256c28?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/9ab411256c28</guid>
            <category><![CDATA[interview]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[walmart]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Mon, 10 Feb 2025 15:18:58 GMT</pubDate>
            <atom:updated>2025-02-11T04:28:05.410Z</atom:updated>
            <content:encoded><![CDATA[<p>Recently, I had the incredible experience of interviewing for an <strong>SDE-III iOS Developer</strong> role at <strong>Walmart</strong>, and I’m thrilled to share that I cleared it! 🎉 This journey wasn’t just about securing a job — it was a testament to my hard work, preparation, and perseverance.</p><p>In this post, I’ll walk you through my <strong>interview process</strong>, the types of <strong>questions</strong> asked, and how this experience boosted my <strong>confidence</strong> as an iOS developer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*39yIcBC3ELqkMbc69_La1A.png" /></figure><h3>Interview Rounds at Walmart</h3><p>The entire process consisted of <strong>four rounds</strong>:</p><ol><li><strong>DSA Round (Data Structures &amp; Algorithms)</strong></li><li><strong>iOS Technical Round</strong></li><li><strong>Hiring Manager Round</strong></li><li><strong>HR Discussion</strong></li></ol><h3>Round 1: DSA (Data Structures &amp; Algorithms)</h3><p>The first round was a classic <strong>coding interview</strong>, where I had to solve <strong>three Leetcode-style problems</strong> within the given time. The questions were:</p><p><a href="https://leetcode.com/problems/squares-of-a-sorted-array/"><strong>Squares of a Sorted Array</strong></a></p><ul><li>This required sorting squared values efficiently, making it a two-pointer problem.</li></ul><p><a href="https://leetcode.com/problems/merge-intervals/"><strong>Merge Intervals</strong></a></p><ul><li>This tested my ability to handle overlapping intervals, which is useful in scheduling problems.</li></ul><p><a href="https://leetcode.com/problems/longest-common-subsequence/"><strong>Longest Common Subsequence</strong></a></p><ul><li>A classic <strong>dynamic programming</strong> problem that tests recursion and memoization.</li></ul><p>I was well-prepared for this round thanks to consistent practice on <strong>Leetcode</strong> and <strong>mock interviews</strong>. I completed all three questions successfully, which gave me a solid start to the process.</p><h3>Round 2: iOS Technical Interview</h3><p>This round focused on <strong>iOS-specific</strong> concepts, covering various topics like:</p><ul><li><strong>Access Specifiers</strong> (private, fileprivate, internal, public, open)</li><li><strong>Open vs Public</strong> (difference in subclassing and module accessibility)</li><li><strong>Grand Central Dispatch (GCD)</strong> (sync vs async, concurrent vs serial)</li><li><strong>Retain Cycle</strong> (how memory leaks occur and how to avoid them)</li><li><strong>Weak vs Unowned</strong> (differences and when to use each)</li><li><strong>Initializers</strong> (designated vs convenience)</li><li><strong>Closures</strong> (escaping vs non-escaping)</li><li><strong>Concurrency</strong> (async/await, actors in Swift)</li><li><strong>Semaphore &amp; NSLock</strong> (handling multi-threading synchronization)</li><li><strong>Core Data</strong> (NSManagedObjectContext, persistent store)</li><li><strong>Static vs Dynamic Frameworks</strong> (difference and when to use each)</li></ul><p>The interviewer didn’t go into deep explanations but expected quick, correct responses. <strong>If I answered confidently, he quickly moved to the next question</strong>, so the key was <strong>concise and accurate explanations</strong>.</p><h3>Round 3: Hiring Manager Discussion</h3><p>This was the round I felt <strong>least confident about</strong> because I was not prepared for <strong>System Design</strong> questions.</p><ul><li>The <strong>Hiring Manager</strong> introduced herself and asked about my background.</li><li>We discussed my <strong>current company’s projects</strong> and the <strong>tech stack</strong> I worked with.</li></ul><p>She asked <strong>in-depth</strong> questions about my current project, such as:</p><ul><li><strong>How do you fetch data?</strong></li><li><strong>Where is the news data stored?</strong></li><li><strong>Who updates the news from the backend?</strong></li><li><strong>How do you handle analytics and crash reports (Firebase Analytics &amp; Crashlytics)?</strong></li></ul><p>Then came <strong>System Design</strong>, which I wasn’t ready for. 😬<br>But I <strong>stayed calm</strong> and designed a system <strong>on the spot</strong>, explaining my thought process.</p><p>Even though I wasn’t confident about this round, <strong>I somehow managed to clear it</strong>!</p><h3>Round 4: HR Discussion</h3><p>This was a <strong>casual conversation</strong> where I was asked:</p><ul><li><strong>Why are you leaving your current company?</strong></li><li><strong>Why Walmart?</strong></li><li><strong>What are your career goals?</strong></li><li><strong>Salary expectations and benefits discussion.</strong></li></ul><p>It was straightforward and mostly about alignment with <strong>Walmart’s culture and values</strong>.</p><h3>Key Takeaways &amp; Lessons Learned</h3><p>✨ <strong>Hard work pays off:</strong> My preparation on <strong>Leetcode, iOS concepts, and past project experiences</strong> helped me answer questions confidently.</p><p>✨ <strong>Confidence matters:</strong> Even when I wasn’t sure about the <strong>System Design round</strong>, I kept my composure and <strong>explained my thought process</strong>, which helped me clear it.</p><p>✨ <strong>Quick and clear answers:</strong> The iOS round moved <strong>fast</strong>. If I hesitated, I might have lost the opportunity. Knowing the fundamentals <strong>inside out</strong> was crucial.</p><p>✨ <strong>Mock interviews help:</strong> Practicing with <strong>mock interviews</strong> and revising <strong>iOS topics</strong> gave me the <strong>speed and clarity</strong>needed in technical rounds.</p><h3>Final Thoughts</h3><p>Clearing <strong>SDE-3 iOS at Walmart</strong> was a <strong>huge confidence boost</strong>. This experience reinforced the idea that <strong>consistent effort and learning</strong> can help you achieve your goals. 🚀</p><p>For anyone preparing for similar roles, my advice is:<br>✅ <strong>Master DSA</strong> (solve at least 100+ Leetcode problems)<br>✅ <strong>Know your iOS concepts deeply</strong><br>✅ <strong>Practice explaining your projects and system design</strong><br>✅ <strong>Stay calm and think on your feet during unexpected questions</strong></p><p>I hope my experience helps you in your journey! 💪 Let me know in the comments if you have any questions. 😃</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9ab411256c28" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Create a Lock Screen Widget in SwiftUI]]></title>
            <link>https://medium.com/@rishixcode/create-a-lock-screen-widget-in-swiftui-070a21f03a3d?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/070a21f03a3d</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift-programming]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Thu, 30 Jan 2025 14:17:28 GMT</pubDate>
            <atom:updated>2025-01-30T14:17:28.785Z</atom:updated>
            <content:encoded><![CDATA[<p>In iOS 16, Apple introduced lock screen widgets, offering users quick access to relevant information without unlocking their devices. Since iOS 17, it’s become easier than ever to create custom lock screen widgets with SwiftUI. In this guide, we’ll walk through the steps to create a simple lock screen widget, specifically a circular widget, which displays a QR code. Let’s dive in!</p><h3>Step 1: Create a New SwiftUI Project</h3><p>First things first, you’ll need to create a new SwiftUI project. Open Xcode and create a new iOS project using the <strong>App</strong>template. Select SwiftUI as the user interface option and choose a name for your project (e.g., <em>LockScreenWidgetApp</em>).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5lV6pPjwq6b1X8oy3fTP0w.png" /></figure><h3>Step 2: Add a Widget Extension</h3><p>Once the project is created, we’ll add a Widget Extension to support creating widgets for the lock screen.</p><ol><li>In the <strong>File</strong> menu, select <strong>New</strong> &gt; <strong>Target</strong>.</li><li>Choose <strong>Widget Extension</strong> under the <strong>iOS</strong> section.</li><li>Name the widget (e.g., <em>SmallWidget</em>).</li><li>Select the <strong>Widget Family</strong> option as <strong>Accessory Circular</strong>, as we’ll be creating a small, circular widget.</li><li>Click <strong>Finish</strong>.</li></ol><p>Now you should see a new widget extension folder in your project, complete with some sample code to get started. We will modify this code for our widget.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h1jQJEGwFwjJVO36ZWYLZA.png" /></figure><h3>Step 3: Design Your Widget View</h3><p>Let’s move to the next step: designing the widget’s interface. For simplicity, we’ll use a switch statement to handle different widget types (although for now, we’ll only add the support for the circular accessory widget).</p><p>In your widget’s EntryView (typically found in SmallWidgetEntryView.swift), replace the existing code with the following:</p><pre>struct SmallWidgetEntryView : View {<br>    var entry: Provider.Entry<br>    @Environment(\.widgetFamily) private var family<br><br>    var body: some View {<br>        switch family {<br>        case .accessoryCircular:<br>            VStack {<br>                Image(systemName: &quot;qrcode&quot;)<br>                    .resizable()<br>                    .padding(12)<br>            }<br>            .frame(maxWidth: .infinity, maxHeight: .infinity)<br>            .background(.black)<br>            .clipShape(.circle)<br><br>        default:<br>            Text(&quot;No Widget Available&quot;)<br>        }<br>    }<br>}</pre><h3>What’s Happening Here?</h3><ul><li>We’re checking the widget family type using @Environment(\.widgetFamily).</li><li>If the widget is an <strong>accessoryCircular</strong>, we’re displaying a QR code image inside a circular frame, with black background and some padding.</li><li>The .clipShape(.circle) modifier ensures that the widget appears as a circle.</li></ul><h3>Step 4: Specify Supported Widget Families</h3><p>Now, let’s tell the system what widget families our widget supports. In the widget’s main struct (found in SmallWidget.swift), replace the code with this:</p><pre>struct SmallWidget: Widget {<br>    let kind: String = &quot;SmallWidget&quot;<br><br>    var body: some WidgetConfiguration {<br>        StaticConfiguration(kind: kind, provider: Provider()) { entry in<br>            if #available(iOS 17.0, *) {<br>                SmallWidgetEntryView(entry: entry)<br>                    .containerBackground(.fill.tertiary, for: .widget)<br>            } else {<br>                SmallWidgetEntryView(entry: entry)<br>                    .padding()<br>                    .background()<br>            }<br>        }<br>        .supportedFamilies([.accessoryCircular]) // Here we specify the widget family<br>        .configurationDisplayName(&quot;My Widget&quot;)<br>        .description(&quot;This is an example widget.&quot;)<br>    }<br>}</pre><h3>Explanation of the Code:</h3><ul><li>StaticConfiguration is used to create a static widget, meaning the content doesn’t change over time.</li><li>We’re using .supportedFamilies([.accessoryCircular]) to tell the system that our widget only supports the <strong>accessoryCircular</strong> widget family.</li><li>The containerBackground modifier is available starting from iOS 17 and gives our widget a background color for the widget container. For earlier versions, a fallback background is used.</li></ul><h3>Step 5: Lock Your Device and Add the Widget</h3><p>Now, let’s test our widget on an actual lock screen. Here’s what you need to do:</p><ol><li><strong>Build and run</strong> the app on a physical device (lock screen widgets only work on physical devices).</li><li>Lock your device.</li><li>Press and hold on the lock screen to enter “Customize” mode.</li><li>Tap <strong>Add Widgets</strong>.</li><li>Look for your widget in the widget selection list and tap on it to add it to your lock screen.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*ZLwUwJWl6EIpBhqni0wWAQ.png" /></figure><h3>Conclusion</h3><p>That’s it! You’ve just created a simple lock screen widget that displays a QR code inside a circular frame. Of course, this is just the beginning. You can expand this by adding more widget families, customizing the view more deeply, or making the content dynamic based on app data.</p><p>Lock screen widgets are a great way to enhance user engagement with your app, and the process in SwiftUI is relatively simple. We hope this guide helps you get started!</p><p>If you have any questions or need further clarification, feel free to leave a comment! Happy coding! 😊</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=070a21f03a3d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Slide to Pay/Unlock Interaction in SwiftUI]]></title>
            <link>https://medium.com/@rishixcode/slide-to-pay-unlock-interaction-in-swiftui-8365b929e185?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/8365b929e185</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[animation]]></category>
            <category><![CDATA[swiggy]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Wed, 15 Jan 2025 03:51:07 GMT</pubDate>
            <atom:updated>2025-01-15T03:51:07.020Z</atom:updated>
            <content:encoded><![CDATA[<h4>Creating a user-friendly and visually appealing payment interaction can make a huge difference in app usability. One such feature, inspired by Swiggy’s “Slide to Pay”, is an interactive slider that confirms the user’s payment. In this blog, we’ll recreate this experience step by step, focusing on smooth animations and intuitive gestures.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2av5PYVC9NPq5ZPK9-ouqA.png" /></figure><h4>The Basics of Drag Gesture</h4><p>To start, we’ll use DragGesture to detect user interaction. A drag gesture tracks the movement of the user’s finger, enabling us to update the slider’s position dynamically.</p><pre>@State var offset: CGFloat = .zero<br>@State var userDragging: Bool = false<br><br>var drag: some Gesture {<br>    DragGesture()<br>        .onChanged { value in<br>            withAnimation {<br>                offset = max(0, value.translation.width)<br>                userDragging = true<br>            }<br>        }<br>        .onEnded { value in<br>            withAnimation {<br>                userDragging = false<br>                if value.translation.width &gt;= (widthOfSlide * 0.7) {<br>                    offset = widthOfSlide - 10<br>                } else {<br>                    offset = .zero<br>                }<br>            }<br>        }<br>}</pre><p>Here, onChanged dynamically updates the slider’s offset as the user drags, while onEnded determines if the slider reaches the threshold for confirmation.</p><h4>Visual Feedback Using GeometryReader</h4><p>Next, we’ll use GeometryReader to dynamically calculate the width of the slider. This ensures our layout adjusts to different screen sizes.</p><pre>var body: some View {<br>    GeometryReader { geometry in<br>        VStack {<br>            Spacer()<br>            ZStack(alignment: .center) {<br>                HStack {<br>                    Image(systemName: &quot;chevron.right.circle.fill&quot;)<br>                        .resizable()<br>                        .frame(width: 50, height: 50)<br>                        .foregroundStyle(.white)<br>                        .padding(.horizontal, 10)<br>                        .offset(x: offset)<br>                        .gesture(drag)<br>                    Spacer()<br>                }<br>                .frame(maxWidth: .infinity)<br>                .frame(height: 70)<br>                .background(.green)<br>                .clipShape(.capsule)<br>                .scaleEffect(userDragging ? 0.99 : 1.0)<br>                .onTapGesture {<br>                    withAnimation {<br>                        userDragging = true<br>                        offset = 20<br>                    }<br>                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {<br>                        withAnimation {<br>                            userDragging = false<br>                            offset = .zero<br>                        }<br>                    }<br>                }<br><br>                Text(&quot;Slide To Pay | ₹255&quot;)<br>                    .opacity(userDragging ? 0.5 : 1.0)<br>                    .foregroundStyle(.white)<br>                    .fontWeight(.bold)<br>                    .font(.title3)<br>            }<br>            .onAppear {<br>                widthOfSlide = geometry.size.width - 50 - 10<br>            }<br>        }<br>    }<br>    .padding()<br>}</pre><p>In this layout, the slider button is dynamically positioned based on offset. We also use onTapGesture to provide visual feedback, where the slider wiggles if the user taps but doesn’t drag.</p><h4>Adding Smooth Animations</h4><p>Animations play a crucial role in enhancing the user experience. Using withAnimation, we ensure the slider snaps back or completes its slide with a polished look.</p><ul><li><strong>Dragging Animation:</strong> Changes the slider’s position in real-time.</li><li><strong>Wiggle Effect:</strong> Briefly shifts the slider to nudge the user into sliding.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*toj67AZF2NzOD5IbUoan8Q.gif" /></figure><h4>Wrapping It All Together</h4><p>Here’s the complete code for our SlideToPay feature:</p><pre>import SwiftUI<br><br>struct ContentView: View {<br><br>    @State var offset: CGFloat = .zero<br>    @State var widthOfSlide: CGFloat = .zero<br>    @State var userDragging: Bool = false<br><br>    var drag: some Gesture {<br>        DragGesture()<br>            .onChanged { value in<br>                withAnimation {<br>                    offset = max(0, value.translation.width)<br>                    userDragging = true<br>                }<br>            }<br>            .onEnded { value in<br>                withAnimation {<br>                    userDragging = false<br>                    if value.translation.width &gt;= (widthOfSlide * 0.7) {<br>                        offset = widthOfSlide - 10<br>                    } else {<br>                        offset = .zero<br>                    }<br>                }<br>            }<br>    }<br><br>    var body: some View {<br>        GeometryReader { geometry in<br>            VStack {<br>                Spacer()<br>                ZStack(alignment: .center) {<br>                    HStack {<br>                        Image(systemName: &quot;chevron.right.circle.fill&quot;)<br>                            .resizable()<br>                            .frame(width: 50, height: 50)<br>                            .foregroundStyle(.white)<br>                            .padding(.horizontal, 10)<br>                            .offset(x: offset)<br>                            .gesture(drag)<br>                        Spacer()<br>                    }<br>                    .frame(maxWidth: .infinity)<br>                    .frame(height: 70)<br>                    .background(.green)<br>                    .clipShape(.capsule)<br>                    .scaleEffect(userDragging ? 0.99 : 1.0)<br>                    .onTapGesture {<br>                        withAnimation {<br>                            userDragging = true<br>                            offset = 20<br>                        }<br>                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {<br>                            withAnimation {<br>                                userDragging = false<br>                                offset = .zero<br>                            }<br>                        }<br>                    }<br><br>                    Text(&quot;Slide To Pay | ₹255&quot;)<br>                        .opacity(userDragging ? 0.5 : 1.0)<br>                        .foregroundStyle(.white)<br>                        .fontWeight(.bold)<br>                        .font(.title3)<br>                }<br>                .onAppear {<br>                    widthOfSlide = geometry.size.width - 50 - 10<br>                }<br>            }<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><p>Let me know if you have any questions or if there’s a particular topic you’d like me to cover next.</p><p>Drop some claps 👏👏👏 if you found this helpful 💡 <br>All and any feedback is accepted. 📩</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8365b929e185" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[QR Scanner View Animation in SwiftUI]]></title>
            <link>https://medium.com/@rishixcode/qr-scanner-view-animation-in-swiftui-c5792f5106e1?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/c5792f5106e1</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[animation]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Mon, 02 Dec 2024 15:14:49 GMT</pubDate>
            <atom:updated>2024-12-02T15:14:49.208Z</atom:updated>
            <content:encoded><![CDATA[<h4>If you’ve seen PhonePe’s QR scanner, you know how engaging and smooth the animation is. Inspired by that, I created a similar QR scanner animation in SwiftUI. In this blog, I’ll break down the code and explain how you can replicate this effect for your app.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o2WkUCD4g3XyIqZ80HLG-g.png" /></figure><h3>Step 1: Setting Up the ScannerView</h3><p>The ScannerView forms the main structure of our QR scanner. It includes a semi-transparent background, a scanning area, and some branding at the bottom.</p><pre>struct ScannerView: View {<br>    @State var animate: Bool = false<br>    <br>    var body: some View {<br>        ZStack {<br>            Rectangle()<br>                .fill(.black.opacity(0.2)) // Semi-transparent overlay<br>            <br>            ScannerAreaView(animate: $animate) // Scanner area with animation<br>                .offset(y: -100) // Adjust vertical position<br>            <br>            VStack {<br>                Spacer()<br>                // Branding images<br>                HStack {<br>                    Image(&quot;bhim&quot;)<br>                        .resizable()<br>                        .frame(width: 70, height: 20)<br>                    Image(&quot;upi&quot;)<br>                        .resizable()<br>                        .frame(width: 50, height: 20)<br>                }<br>                .padding(40)<br>            }<br>        }<br>        .compositingGroup() // For rendering effects<br>        .frame(maxWidth: .infinity, maxHeight: .infinity)<br>    }<br>}</pre><h4>Key Features:</h4><ol><li><strong>Background Overlay:</strong> The rectangle with .black.opacity(0.2) gives the scanner its signature dimmed background.</li><li><strong>Branding Section:</strong> At the bottom, I included BHIM and UPI logos to mimic real-world QR scanner branding.</li></ol><h3>Step 2: Creating the Animated Edges</h3><p>The EdgeRectangleView creates the animated stroke effect around the scanner area.</p><pre>struct EdgeRectangleView: View {<br>    @Binding var animate: Bool<br>    <br>    var body: some View {<br>        RoundedRectangle(cornerRadius: 20)<br>            .trim(from: animate ? 0.35 : 0.34, to: animate ? 0.4 : 0.41) // Vary stroke size<br>            .stroke(<br>                Color(red: 132/255, green: 44/255, blue: 240/255), <br>                style: StrokeStyle(lineWidth: 10, lineCap: .round)<br>            )<br>    }<br>}</pre><h4>Key Features:</h4><ol><li><strong>Trimming for Animation:</strong> The .trim() function animates a small section of the rectangle’s border, giving a scanning effect.</li><li><strong>Dynamic Color:</strong> The vibrant purple stroke color adds a premium feel.</li></ol><h3>Step 3: Assembling the Scanner Area</h3><p>The ScannerAreaView is the core of the scanner&#39;s animation. It combines the edge animations and applies a scaling effect to simulate scanning.</p><pre>struct ScannerAreaView: View {<br>    @Binding var animate: Bool<br>    var rotationDegrees: [Double] = [0, 90, 180, 270]<br>    @State var timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()<br><br>    var body: some View {<br>        ZStack {<br>            Rectangle()<br>                .blendMode(.destinationOut) // Makes the scanner area transparent<br>                .clipShape(.rect(cornerRadius: 20)) // Custom shape<br>            <br>            ForEach(0..&lt;4) { item in<br>                EdgeRectangleView(animate: $animate)<br>                    .rotationEffect(Angle(degrees: rotationDegrees[item])) // Rotate edges<br>            }<br>            .padding(20) // Adjust spacing<br>        }<br>        .onReceive(timer, perform: { _ in<br>            animate.toggle() // Toggle animation state<br>        })<br>        .frame(width: animate ? 320 : 300, height: animate ? 320 : 300) // Scaling effect<br>        .animation(.easeInOut(duration: 0.9), value: animate) // Smooth animation<br>    }<br>}</pre><h4>Key Features:</h4><ol><li><strong>Rotating Edges:</strong> The rotationEffect rotates each edge rectangle by 90 degrees to position them around the scanner area.</li><li><strong>Scaling Effect:</strong> The animate state changes the scanner size dynamically, giving a pulsing effect.</li><li><strong>Timer-Based Animation:</strong> A Timer toggles the animate state every second to create a seamless loop.</li></ol><h3>Step 4: Preview the View</h3><p>Finally, ensure the ScannerView is connected to your preview provider to test its appearance in Xcode.</p><pre>#Preview {<br>    ScannerView()<br>}</pre><h3>Explaining the Key Visual Effects</h3><ol><li><strong>Blend Mode: </strong>The .blendMode(.destinationOut) ensures that the scanning area is cut out from the dimmed background, creating a transparent region.</li><li><strong>Custom Shapes: </strong>The .rect(cornerRadius: 20) creates rounded corners for the scanner area, enhancing the aesthetic.</li><li><strong>Smooth Animations: </strong>The combination of .animation and .easeInOut ensures the scaling and edge animations are visually appealing.</li></ol><h3>How to Customize</h3><ol><li><strong>Change Colors: </strong>Modify the stroke color in EdgeRectangleView to match your app&#39;s theme.</li><li><strong>Adjust Animation Duration: </strong>Play around with the duration value in .animation() for faster or slower animations.</li><li><strong>Add More Branding: </strong>Include additional elements like a logo or a help button for a more functional scanner.</li></ol><h3>Conclusion</h3><p>This QR scanner animation is visually appealing and functional, perfect for any app that uses QR codes. It demonstrates the power and flexibility of SwiftUI in creating complex animations with minimal code. By breaking down the animation into reusable components, you can easily adapt it to your needs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/444/1*VU0MVK-dHzC2MfjTog6MoA.gif" /></figure><p>You can checkout the complete code with CodeScanner SPM integrated available on <a href="https://github.com/Rishabhhx/PhonePeQR">Github</a> 👈</p><p>Let me know if you have any questions or if there’s a particular topic you’d like me to cover next.</p><p>Drop some claps 👏👏👏 if you found this helpful 💡 <br>All and any feedback is accepted. 📩</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c5792f5106e1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AppDelegate and SceneDelegate in SwiftUI]]></title>
            <link>https://medium.com/@rishixcode/appdelegate-and-scenedelegate-in-swiftui-729e8ab6ee2d?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/729e8ab6ee2d</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Fri, 18 Oct 2024 12:51:45 GMT</pubDate>
            <atom:updated>2024-10-18T12:51:45.121Z</atom:updated>
            <content:encoded><![CDATA[<h4>When SwiftUI was introduced, it brought a declarative syntax for building UIs and abstracted away a lot of boilerplate code that developers were used to in UIKit. One of the most noticeable changes was how SwiftUI apps manage their lifecycle, reducing our need for classes like AppDelegate and SceneDelegate. However, there are still times when you may need to implement them.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*txkt6d6uWQWDh-a4zPbQBA.png" /></figure><p>In this blog, I’ll walk you through how the SwiftUI app lifecycle works, how to manage app state changes using ScenePhase, and when and how to reintroduce AppDelegate if you need it. Let&#39;s get started!</p><h3>1. The SwiftUI Way: Managing Lifecycle with ScenePhase</h3><p>The app’s lifecycle in SwiftUI is much cleaner than it was in UIKit, thanks to the @main keyword and the App protocol. Instead of relying on AppDelegate for lifecycle events, SwiftUI provides an @Environment variable for tracking the app’s lifecycle state, called scenePhase.</p><p>Let’s start by creating a simple SwiftUI app that tracks whether the app is active, inactive, or in the background.</p><pre>import SwiftUI<br><br>@main<br>struct TimepassApp: App {<br>    // Using Environment to track scenePhase<br>    @Environment(\.scenePhase) var scenePhase<br>    var body: some Scene {<br>        WindowGroup {<br>            ContentView()<br>        }<br>        .onChange(of: scenePhase) { newPhase in<br>            // Monitoring the app&#39;s lifecycle changes<br>            switch newPhase {<br>            case .active:<br>                print(&quot;App is active&quot;)<br>            case .inactive:<br>                print(&quot;App is inactive&quot;)<br>            case .background:<br>                print(&quot;App is in the background&quot;)<br>            @unknown default:<br>                print(&quot;Unknown state&quot;)<br>            }<br>        }<br>    }<br>}<br>struct ContentView: View {<br>    var body: some View {<br>        Text(&quot;Hello, World!&quot;)<br>            .padding()<br>    }<br>}</pre><h4>Explanation:</h4><ul><li>The @Environment(\.scenePhase) tracks the app’s state and triggers changes based on its phase (active, inactive, or background).</li><li>The .onChange(of:) modifier listens to changes in scenePhase, allowing us to handle the app&#39;s lifecycle events declaratively.</li></ul><p>This is the ideal solution for most apps that don’t need additional control over system-level events at the start.</p><h3>2. Handling Code During App Startup with init()</h3><p>If you want to run any code when your SwiftUI app starts, before the app enters the view hierarchy, you can utilize the init() method in your App struct. This method is ideal for tasks like logging or configuring a service as the app starts.</p><p>Here’s how you can add custom startup logic using the init() method:</p><pre>@main<br>struct TimepassApp: App {<br>    @Environment(\.scenePhase) var scenePhase<br><br>init() {<br>        // Code that runs as soon as the app starts<br>        print(&quot;App has started!&quot;)<br>        // Initialize any services or configurations here<br>    }<br>    var body: some Scene {<br>        WindowGroup {<br>            ContentView()<br>        }<br>        .onChange(of: scenePhase) { newPhase in<br>            switch newPhase {<br>            case .active:<br>                print(&quot;App is active&quot;)<br>            case .inactive:<br>                print(&quot;App is inactive&quot;)<br>            case .background:<br>                print(&quot;App is in the background&quot;)<br>            @unknown default:<br>                print(&quot;Unknown state&quot;)<br>            }<br>        }<br>    }<br>}</pre><h4>Key Points:</h4><ul><li>The init() method is called when the App is first initialized, making it a good place to configure services or set up initial states before any views are loaded.</li></ul><h3>3. When You Still Need AppDelegate</h3><p>In most cases, using scenePhase and the init() method is enough for SwiftUI apps. But, there are times when you may still need access to AppDelegate—for example, when integrating third-party services that require delegate methods like push notifications, deep linking, or background tasks.</p><p>To do that, we can define an AppDelegate class and connect it to our SwiftUI app using UIApplicationDelegateAdaptor. Here&#39;s how you can implement that:</p><pre>import SwiftUI<br><br>// Define your AppDelegate class<br>class AppDelegate: NSObject, UIApplicationDelegate {<br>    func application(<br>        _ application: UIApplication,<br>        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil<br>    ) -&gt; Bool {<br>        // Perform any setup when the app finishes launching<br>        print(&quot;AppDelegate: App has finished launching&quot;)<br>        return true<br>    }<br>    <br>    // Implement other AppDelegate methods if needed<br>}<br><br>@main<br>struct TimepassApp: App {<br>    // Connecting AppDelegate with the app using UIApplicationDelegateAdaptor<br>    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate<br>    @Environment(\.scenePhase) var scenePhase<br><br>    var body: some Scene {<br>        WindowGroup {<br>            ContentView()<br>        }<br>        .onChange(of: scenePhase) { newPhase in<br>            switch newPhase {<br>            case .active:<br>                print(&quot;App is active&quot;)<br>            case .inactive:<br>                print(&quot;App is inactive&quot;)<br>            case .background:<br>                print(&quot;App is in the background&quot;)<br>            @unknown default:<br>                print(&quot;Unknown state&quot;)<br>            }<br>        }<br>    }<br>}</pre><h4>Explanation:</h4><ul><li>The AppDelegate class is back, but now we use UIApplicationDelegateAdaptor to integrate it with the SwiftUI app.</li><li>This allows you to handle AppDelegate lifecycle events (like push notifications or background tasks) while still taking advantage of SwiftUI&#39;s declarative lifecycle management with scenePhase.</li></ul><h3>Conclusion</h3><p>With SwiftUI, you can now manage most of your app’s lifecycle using scenePhase, making your code cleaner and more declarative. For startup logic, the init() method in your App struct is often enough. But when you need more fine-grained control, or you’re dealing with third-party integrations that rely on AppDelegate, you can still bring it back into your SwiftUI app using UIApplicationDelegateAdaptor.</p><p>Whether you’re starting a new SwiftUI project or transitioning from UIKit, understanding how these lifecycle features work will ensure you can handle both simple and advanced use cases. Happy coding! 😄</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=729e8ab6ee2d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[List Swipe Actions in SwiftUI]]></title>
            <link>https://medium.com/@rishixcode/list-swipe-actions-in-swiftui-093dc1459f9d?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/093dc1459f9d</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Mon, 14 Oct 2024 12:04:46 GMT</pubDate>
            <atom:updated>2024-10-14T12:04:46.893Z</atom:updated>
            <content:encoded><![CDATA[<p>In this blog, we’ll walk through the process of adding custom swipe actions to a List in SwiftUI. We&#39;ll start by creating a simple list of colored rectangles, then explore how to implement leading and trailing swipe actions to handle actions like marking an item as done, deleting, or editing it. We&#39;ll also customize the appearance of these swipe actions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*5CvCBgNrdYf1dTNccIy8gg.gif" /></figure><h3>Creating the List with ForEach</h3><p>We begin by creating a simple List that displays colored rectangles. The colors will be provided using an array of gradient colors, and we&#39;ll iterate over this array using a ForEach loop.</p><p>Here’s the basic structure of our view:</p><pre>struct ListView: View {<br>    let colors = [<br>        Color.blue.gradient,<br>        Color.red.gradient,<br>        Color.green.gradient,<br>        Color.blue.gradient,<br>        Color.red.gradient,<br>        Color.green.gradient<br>    ]<br>    <br>    var body: some View {<br>        List {<br>            ForEach(Array(colors.enumerated()), id: \.offset) { index, color in<br>                Rectangle()<br>                    .fill(color)<br>                    .frame(maxWidth: .infinity)<br>                    .frame(height: 90)<br>                    .clipShape(.rect(cornerRadius: 15))<br>                    .padding()<br>                    .listRowInsets(EdgeInsets())<br>            }<br>        }<br>        .listStyle(.plain)<br>        .frame(maxWidth: .infinity, maxHeight: .infinity)<br>    }<br>}</pre><h3>Explanation:</h3><ul><li><strong>List</strong>: This is the main container that represents a vertically scrolling view. Each item in the list will be created by iterating over the array of colors.</li><li><strong>ForEach</strong>: This loop helps iterate over the colors array, creating a Rectangle for each color.</li><li><strong>Rectangle</strong>: We use this shape to fill each list item with a colored rectangle, setting its width, height, and corner radius for a rounded design.</li></ul><p>Next, we’ll make our list items interactive by adding swipe actions.</p><h3>Adding Swipe Actions to the List</h3><p>In SwiftUI, you can easily add swipe actions to a List item by using the .swipeActions modifier. This can be done for both leading and trailing edges, enabling actions like editing, deleting, or marking as complete.</p><p>Let’s add two swipe actions: one on the <strong>leading</strong> edge and two on the <strong>trailing</strong> edge.</p><pre>List {<br>    ForEach(Array(colors.enumerated()), id: \.offset) { index, color in<br>        Rectangle()<br>            .fill(color)<br>            .frame(maxWidth: .infinity)<br>            .frame(height: 90)<br>            .clipShape(.rect(cornerRadius: 15))<br>            .padding()<br>            .listRowInsets(EdgeInsets())<br>            .swipeActions(edge: .leading) {<br>                completeAction()<br>            }<br>            .swipeActions(edge: .trailing) {<br>                deleteAction()<br>                editAction()<br>            }<br>    }<br>}</pre><h3>Explanation:</h3><ul><li><strong>swipeActions(edge: .leading)</strong>: This adds a swipe action to the leading (left) edge of each list item. We’ll use this for marking an item as done.</li><li><strong>swipeActions(edge: .trailing)</strong>: This adds a swipe action to the trailing (right) edge. Here, we’ll add delete and edit actions.</li></ul><h3>Creating the Views for Swipe Actions</h3><p>Now that the basic structure is in place, let’s define the views for the swipe actions: <strong>Mark Done</strong>, <strong>Delete</strong>, and <strong>Edit</strong>. Each action will have an icon and a label, with appropriate tint colors.</p><h3>Complete (Mark Done) Action</h3><pre>private func completeAction() -&gt; some View {<br>    Button {<br>        // Handle mark as done action<br>    } label: {<br>        VStack {<br>            Image(systemName: &quot;checkmark.circle.fill&quot;)<br>            Text(&quot;Mark Done&quot;)<br>        }<br>    }<br>    .tint(.green)<br>}</pre><p>This action marks the list item as complete and uses the green color for a positive action.</p><h3>Delete Action</h3><pre>private func deleteAction() -&gt; some View {<br>    Button(role: .destructive) {<br>        // Handle delete action<br>    } label: {<br>        VStack {<br>            Image(systemName: &quot;wrongwaysign.fill&quot;)<br>            Text(&quot;Delete&quot;)<br>        }<br>    }<br>    .tint(.red)<br>}</pre><p>The delete action is destructive, as indicated by the red tint and the role: .destructive. The destructive role automatically handles accessibility features like confirmation.</p><h3>Edit Action</h3><pre>private func editAction() -&gt; some View {<br>    Button {<br>        // Handle edit action<br>    } label: {<br>        VStack {<br>            Image(systemName: &quot;note.text&quot;)<br>            Text(&quot;Edit&quot;)<br>        }<br>    }<br>    .tint(Color(red: 255/255, green: 128/255, blue: 0/255))<br>}</pre><p>For the edit action, we use an orange tint. It includes an icon and a label to make the action clear to users.</p><h3>Putting It All Together</h3><p>Here’s the final code that combines everything:</p><pre>struct ListView: View {<br>    let colors = [<br>        Color.blue.gradient,<br>        Color.red.gradient,<br>        Color.green.gradient,<br>        Color.blue.gradient,<br>        Color.red.gradient,<br>        Color.green.gradient<br>    ]<br>    <br>    var body: some View {<br>        List {<br>            ForEach(Array(colors.enumerated()), id: \.offset) { index, color in<br>                Rectangle()<br>                    .fill(color)<br>                    .frame(maxWidth: .infinity)<br>                    .frame(height: 90)<br>                    .clipShape(.rect(cornerRadius: 15))<br>                    .padding()<br>                    .listRowInsets(EdgeInsets())<br>                    .swipeActions(edge: .leading) {<br>                        completeAction()<br>                    }<br>                    .swipeActions(edge: .trailing) {<br>                        deleteAction()<br>                        editAction()<br>                    }<br>            }<br>        }<br>        .listStyle(.plain)<br>        .frame(maxWidth: .infinity, maxHeight: .infinity)<br>    }<br>    <br>    private func completeAction() -&gt; some View {<br>        Button {<br>            // Handle mark as done action<br>        } label: {<br>            VStack {<br>                Image(systemName: &quot;checkmark.circle.fill&quot;)<br>                Text(&quot;Mark Done&quot;)<br>            }<br>        }<br>        .tint(.green)<br>    }<br>    <br>    private func deleteAction() -&gt; some View {<br>        Button(role: .destructive) {<br>            // Handle delete action<br>        } label: {<br>            VStack {<br>                Image(systemName: &quot;wrongwaysign.fill&quot;)<br>                Text(&quot;Delete&quot;)<br>            }<br>        }<br>        .tint(.red)<br>    }<br>    <br>    private func editAction() -&gt; some View {<br>        Button {<br>            // Handle edit action<br>        } label: {<br>            VStack {<br>                Image(systemName: &quot;note.text&quot;)<br>                Text(&quot;Edit&quot;)<br>            }<br>        }<br>        .tint(Color(red: 255/255, green: 128/255, blue: 0/255))<br>    }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*XZ29DrwDtGlqeooCRhJ2sA.gif" /></figure><h3>Conclusion</h3><p>SwiftUI makes it incredibly easy to add swipe actions to a List, enhancing the interactivity and UX of your app. With just a few lines of code, we can introduce leading and trailing swipe gestures for actions like marking an item as complete, deleting, or editing.</p><p>Let me know if you have any questions or if there’s a particular topic you’d like me to cover next.</p><p>Drop some claps 👏👏👏 if you found this helpful 💡 <br>All and any feedback is accepted. 📩</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=093dc1459f9d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Notification Stack Animation in SwiftUI]]></title>
            <link>https://medium.com/@rishixcode/notification-stack-animation-in-swiftui-6a11af8abced?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/6a11af8abced</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[animation]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[uikit]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Mon, 07 Oct 2024 13:07:43 GMT</pubDate>
            <atom:updated>2024-10-07T13:07:43.342Z</atom:updated>
            <content:encoded><![CDATA[<h4>Animations are one of the most delightful ways to enhance user experience in modern app development. With SwiftUI, creating custom animations has become much easier and more flexible. In this tutorial, I’ll walk you through building a <strong>notification stack</strong> that smoothly expands and collapses cards, with each card in the stack sliding into position as it animates.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*M9Zhk2sTQ5f5iJY2z1y8uA.gif" /></figure><h4>Let’s go step by step, starting from defining our properties to adding the animated behaviors. By the end of this blog, you’ll understand how the code works and how to apply similar principles to other animations.</h4><blockquote><strong>💡 If you want to directly jump to complete code scroll to bottom.</strong></blockquote><h3>Step 1: Defining the Properties</h3><p>We’ll begin by defining the properties for our <strong>NotificationStack</strong>. This stack will contain multiple cards that animate when tapped.</p><pre>struct NotificationStack: View {<br>    @State var isExpanded = false<br>    let cellHeight = 80<br>    let colors : [Color] = [.yellow, .pink, .indigo, .green, .red, .orange]</pre><p>Here:</p><ul><li><strong>@State var isExpanded</strong>: This Boolean state will help us track if the stack is expanded or collapsed. When isExpanded is true, the cards spread out; when false, they collapse into each other.</li><li><strong>cellHeight</strong>: Defines the height of each card in the stack.</li><li><strong>colors</strong>: We are using an array of colors for each card. SwiftUI’s color support is awesome for building visual effects quickly.</li></ul><h3>Step 2: Using LazyVStack for Performance</h3><p>We are using <strong>LazyVStack</strong> for creating our vertical stack of cards. It’s like a VStack, but <strong>LazyVStack</strong> only renders the views that are currently visible, providing better performance in certain scenarios, especially when working with long lists.</p><pre>VStack {<br>    LazyVStack(spacing: isExpanded ? 20 : -Double(cellHeight)) {</pre><p>The spacing between the cards is dynamic here: if the stack is expanded, we want more space between the cards, but when collapsed, the cards should overlap.</p><h3>Step 3: Adding the Text Elements with ForEach</h3><p>Next, we use <strong>ForEach</strong> to iterate over the color array, creating a card for each color.</p><pre>ForEach(0..&lt;colors.count, id: \.self) { index in<br>    Text(&quot;Card \(index)&quot;)<br>        .frame(height: CGFloat(cellHeight))<br>        .frame(maxWidth: .infinity)<br>        .background(colors[index].gradient)<br>        .clipShape(.rect(cornerRadius: 18))<br>        .padding(.horizontal)</pre><p>Here, we create text elements (which represent our “cards”) and assign each a color from the array. The card also has rounded corners with a <strong>clipShape</strong> modifier and some horizontal padding for aesthetics.</p><h3>Step 4: Managing ZIndex and Offsets</h3><p>Without controlling the <strong>zIndex</strong>, the cards would simply stack in their natural order, meaning the last card would be on top. We want the first card to be on top when collapsed.</p><pre>.zIndex(Double(colors.count - index))</pre><p>This line ensures that the first card has the highest z-index (layer position), and each subsequent card is stacked behind the previous one.</p><p>We then control the positioning of the cards based on whether the stack is expanded or not:</p><pre>.offset(x: 0, y: getOffset(index: index))</pre><p>We calculate the <strong>offset</strong> (vertical shift) using the getOffset(index:) function, which I’ll explain in detail later.</p><h3>Step 5: Adding Opacity and Dynamic Padding</h3><p>We also want to control the <strong>opacity</strong> of each card when the stack is collapsed, giving the appearance of cards disappearing as they move farther down the stack.</p><pre>.opacity(getOpacity(with: index))<br>.padding(.horizontal, getHorizonatalPadding(index: index))</pre><p>Here, both <strong>opacity</strong> and <strong>padding</strong> are dynamically set based on the index, which makes the visual effect more polished.</p><h3>Step 6: Grouping for Smooth Animation</h3><p>SwiftUI animations can sometimes be jerky if the changes to views are not grouped together properly. To avoid this, we use:</p><pre>.geometryGroup()</pre><p>This groups our geometry changes so that SwiftUI understands them as a single unit, allowing for a smoother animation experience.</p><h3>Step 7: Adding Tap Gesture and Triggering Animation</h3><p>Finally, we make the cards interactive by adding a tap gesture. When tapped, the <strong>isExpanded</strong> state toggles between trueand false, triggering the animation.</p><pre>.onTapGesture {<br>    withAnimation {<br>        isExpanded.toggle()<br>    }<br>}</pre><p>By wrapping the state change in <strong>withAnimation { ... }</strong>, SwiftUI automatically animates the relevant view changes.\</p><h3>Step 8: Private Helper Functions</h3><p>Now, let’s break down the helper functions that control the behavior of our cards.</p><h4>getOffset(index:)</h4><p>This function calculates how much each card should shift vertically depending on whether the stack is expanded or collapsed.</p><pre>func getOffset(index: Int) -&gt; CGFloat {<br>    if isExpanded {<br>        return 0<br>    } else {<br>        switch index {<br>        case 0: return 0<br>        case 1: return CGFloat(10)<br>        case 2: return CGFloat(20)<br>        default: return CGFloat(20)<br>        }<br>    }<br>}</pre><p>When the stack is collapsed, the first card stays in place, while the following cards shift downward by 10 and 20 points respectively.</p><h4>getHorizonatalPadding(index:)</h4><p>This function handles the horizontal padding to give each card a slightly indented appearance when collapsed.</p><pre>func getHorizonatalPadding(index: Int) -&gt; CGFloat {<br>    if isExpanded {<br>        return 0<br>    } else {<br>        switch index {<br>        case 0: return 0<br>        case 1: return 5<br>        case 2: return 10<br>        default: return 10<br>        }<br>    }<br>}</pre><p>When collapsed, each subsequent card has a bit more horizontal padding than the previous, contributing to the stacked effect.</p><h4>getOpacity(with:)</h4><p>Finally, we handle the <strong>opacity</strong> of each card to make the cards gradually disappear as they move down the stack.</p><pre>func getOpacity(with index: Int) -&gt; Double {<br>    if isExpanded {<br>        return 1<br>    } else {<br>        switch index {<br>        case 0: return 1<br>        case 1: return 0.75<br>        case 2: return 0.5<br>        default: return 0<br>        }<br>    }<br>}</pre><p>Cards at the bottom of the stack have less opacity when collapsed, creating a fading effect.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*8GIqISmm4S945Gee61zSeg.gif" /></figure><h3>Final Thoughts</h3><p>That’s it! You’ve built a <strong>notification stack animation</strong> with SwiftUI. With simple state management and some clever use of animations and view modifiers, you can create a visually engaging experience for users. Try experimenting with different stack behaviors, colors, and shapes to customize this to your app’s design needs.</p><h3>Complete Code 🫡</h3><pre>import SwiftUI<br><br>struct NotificationStack: View {<br>    @State var isExpanded = false<br>    let cellHeight = 80<br>    let colors : [Color] = [.yellow, .pink, .indigo, .green, .red, .orange]<br>    <br>    var body: some View {<br>        VStack {<br>            LazyVStack(spacing: isExpanded ? 20 :  -Double(cellHeight)) {<br>                ForEach(0..&lt;colors.count, id: \.self) { index in<br>                    Text(&quot;Card \(index)&quot;)<br>                        .frame(height: CGFloat(cellHeight))<br>                        .frame(maxWidth: .infinity)<br>                        .background(colors[index].gradient)<br>                        .clipShape(.rect(cornerRadius: 18))<br>                        .padding(.horizontal)<br>                    // if we dont manage the zindex then last view will be on top, we want first to be on top<br>                        .zIndex(Double(colors.count - index))<br>                        .offset(x: 0, y: getOffset(index: index))<br>                        .opacity(getOpacity(with: index))<br>                        .padding(.horizontal, getHorizonatalPadding(index: index))<br>                    // handles smooth animation by taking elements insded a view as group<br>                        .geometryGroup()<br>                        .onTapGesture {<br>                            withAnimation {<br>                                isExpanded.toggle()<br>                            }<br>                        }<br>                }<br>            }<br>            .padding(.vertical)<br>            Spacer()<br>        }<br>        .frame(maxWidth: .infinity, alignment: .top)<br>    }<br>}<br><br>private extension NotificationStack {<br>    func getOffset(index: Int) -&gt; CGFloat {<br>        if isExpanded {<br>            return 0<br>        } else {<br>            switch index {<br>            case 0: return 0<br>            case 1: return CGFloat(10)<br>            case 2: return CGFloat(20)<br>            default: return CGFloat(20)<br>            }<br>        }<br>    }<br>    <br>    func getHorizonatalPadding(index: Int) -&gt; CGFloat {<br>        if isExpanded {<br>            return 0<br>        } else {<br>            switch index {<br>            case 0: return 0<br>            case 1: return 5<br>            case 2: return 10<br>            default: return 10<br>            }<br>        }<br>    }<br>    <br>    func getOpacity(with index: Int) -&gt; Double {<br>        if isExpanded {<br>            return 1<br>        } else {<br>            switch index {<br>            case 0: return 1<br>            case 1: return 0.75<br>            case 2: return 0.5<br>            default: return 0<br>            }<br>        }<br>    }<br>}</pre><p>Let me know if you have any questions or if there’s a particular topic you’d like me to cover next.</p><p>Drop some claps 👏👏👏 if you found this helpful 💡 <br>All and any feedback is accepted. 📩</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6a11af8abced" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Instagram-Like Animation in SwiftUI]]></title>
            <link>https://medium.com/@rishixcode/instagram-like-animation-in-swiftui-7b3fe84a2c4b?source=rss-f86c9c34c98e------2</link>
            <guid isPermaLink="false">https://medium.com/p/7b3fe84a2c4b</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[animation]]></category>
            <dc:creator><![CDATA[Rishabh Sharma]]></dc:creator>
            <pubDate>Sun, 22 Sep 2024 17:00:33 GMT</pubDate>
            <atom:updated>2024-09-22T17:05:52.626Z</atom:updated>
            <content:encoded><![CDATA[<h4>Imagine you’re scrolling through Instagram, and you see a post you love. What do you do? Double-tap, and a heart appears with a delightful animation! That little heart popping up, bouncing, and flying away is a tiny moment of joy in the user experience. In this tutorial, we’re going to recreate that iconic animation using SwiftUI.</h4><p>By the end of this blog, you’ll have a clear understanding of how to create a beautiful, animated heart that appears at the tap location and then gracefully flies away. Let’s dive in!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RxLrN3E_2s3r0upISZ4VMw.png" /></figure><h3>The Heart of the Matter: Understanding the Code</h3><p>Let’s break down the code step by step, so you can see how it all comes together.</p><h4>1. Defining the Model</h4><pre>struct HeartModel: Hashable, Identifiable {<br>    var id = UUID()<br>    var location: CGPoint<br>}</pre><p><strong>Explanation:</strong><br>We start with a simple model, HeartModel, which conforms to Hashable and Identifiable. This model will represent each heart that appears on the screen. It contains a unique id to differentiate between hearts and a location property to store where the user tapped on the screen.</p><ul><li><strong>id = UUID()</strong>: Automatically generates a unique identifier for each heart, essential for distinguishing between multiple hearts on the screen.</li><li><strong>location: CGPoint</strong>: Stores the x and y coordinates where the heart should appear.</li></ul><h4>2. Building the View: The Main Component</h4><pre>struct InstaLike: View {<br>    @State var heartsToDisplay: [HeartModel] = []<br>    <br>    var body: some View {<br>        ZStack {<br>            ForEach(heartsToDisplay) { heart in<br>                HeartView(heartObj: heart)<br>            }<br>        }<br>        .frame(maxWidth: .infinity, maxHeight: .infinity)<br>        .ignoresSafeArea(edges: .all)<br>        .background(Color(red: 40/255, green: 40/255, blue: 40/255))<br>        .onTapGesture { location in<br>            let heart = HeartModel(location: location)<br>            heartsToDisplay.append(heart)<br>            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {<br>                heartsToDisplay.removeAll(where: {$0.id == heart.id})<br>            }<br>        }<br>    }<br>}</pre><p><strong>Explanation:</strong><br>The InstaLike view is where the magic happens. This view is responsible for displaying the hearts and handling user interactions.</p><ul><li><strong>@State var heartsToDisplay: [HeartModel] = []</strong>: This state variable holds an array of HeartModel objects. Every time the user taps, a new heart is added to this array, which triggers the view to update and display the new heart.</li><li><strong>ZStack</strong>: All hearts are stacked on top of each other using a ZStack. As new hearts are added, they’re rendered on top of previous ones.</li><li><strong>.onTapGesture</strong>: This modifier handles the tap gesture. When the user taps, we capture the tap location, create a new HeartModel with that location, and append it to heartsToDisplay.</li><li><strong>DispatchQueue.main.asyncAfter</strong>: We delay the removal of the heart by 1 second, giving it time to animate before disappearing.</li></ul><h4>3. Crafting the Heart: The Animation View</h4><pre>struct HeartView: View {<br>    @State var heartObj: HeartModel<br>    @State var showHeart: Bool = false<br>    @State var rotate: Bool = false<br>    @State var fly: Bool = false<br>    <br>    var body: some View {<br>        GeometryReader { reader in<br>            ZStack {<br>                Image(systemName: &quot;heart.fill&quot;)<br>                    .resizable()<br>                    .frame(width: 100, height: 100)<br>                    .foregroundStyle(<br>                        .linearGradient(<br>                            colors: [.purple, .pink, .pink, .orange],<br>                            startPoint: .topLeading,<br>                            endPoint: .bottomTrailing)<br>                    )<br>                    .symbolEffect(.bounce, value: showHeart)<br>                    .symbolEffect(.wiggle.clockwise, value: showHeart)<br>                    .opacity(showHeart ? 1 : 0)<br>                    .offset(x: fly ? (reader.size.width/2 - 40) : heartObj.location.x - 50, y: fly ? (heartObj.location.y - reader.size.height) : heartObj.location.y)<br>                    .onAppear() {<br>                        print(reader.size.width/2)<br>                        withAnimation(.easeInOut(duration: 0.2)) {<br>                            showHeart.toggle()<br>                        }<br>                        withAnimation(.snappy(duration: 0.5).delay(0.6)) {<br>                            fly.toggle()<br>                        }<br>                    }<br>            }<br>        }<br>        .ignoresSafeArea(edges: .all)<br>    }<br>}</pre><p><strong>Explanation:</strong><br>The HeartView is the star of the show. It’s responsible for displaying the heart and animating it.</p><ul><li><strong>@State var showHeart: Bool = false</strong>: Controls the visibility of the heart. Initially, it&#39;s hidden, and then it fades in with an animation.</li><li><strong>@State var fly: Bool = false</strong>: Controls the flying effect of the heart. It starts at the tap location and then moves upwards and towards the center of the screen.</li><li><strong>GeometryReader</strong>: This view helps us get the dimensions of the available space. It&#39;s crucial for calculating the position where the heart should move.</li><li><strong>Image(systemName: &quot;heart.fill&quot;)</strong>: The heart image is drawn using SF Symbols. We apply a gradient to make it visually appealing.</li><li><strong>.symbolEffect(.bounce, value: showHeart)</strong>: A fun little bounce effect is applied to the heart when it appears.</li><li><strong>.opacity(showHeart ? 1 : 0)</strong>: The heart starts off invisible and fades in when showHeart toggles.</li><li><strong>.offset</strong>: The heart&#39;s position is adjusted based on the user&#39;s tap location, and then it flies upwards.</li><li><strong>.onAppear()</strong>: This modifier triggers when the view appears on the screen. We animate the heart’s appearance and movement in sequence.</li></ul><h3>Wrapping Up</h3><p>With just a few lines of SwiftUI code, we’ve recreated the Instagram-like animation. This example shows the power of SwiftUI in making complex animations feel straightforward and accessible. Whether you’re creating a social media app or just want to add some flair to your app, this animation can be a great addition.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F72lTN1HlaLaIbdIxMKpSg.gif" /></figure><p>I hope this breakdown helps you understand how to work with SwiftUI’s animation capabilities. Feel free to customize the heart’s size, color, or animation to fit your app’s theme. Happy coding, and keep creating amazing experiences!</p><p>Let me know if you have any questions or if there’s a particular topic you’d like me to cover next.</p><p>Drop some claps 👏👏👏 if you found this helpful 💡 <br>All and any feedback is accepted. 📩</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7b3fe84a2c4b" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>