<?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 enebin on Medium]]></title>
        <description><![CDATA[Stories by enebin on Medium]]></description>
        <link>https://medium.com/@enebin?source=rss-84589cdcce2f------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*ewOdJokLIFa_ME4UjR-MjA.jpeg</url>
            <title>Stories by enebin on Medium</title>
            <link>https://medium.com/@enebin?source=rss-84589cdcce2f------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 28 May 2026 21:15:02 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@enebin/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[I Built an App Because AI Agent Workflows Were Becoming Invisible]]></title>
            <link>https://enebin.medium.com/i-built-an-app-because-ai-agent-workflows-were-becoming-invisible-85865c1402ca?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/85865c1402ca</guid>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[generative-ai-tools]]></category>
            <category><![CDATA[chatgpt]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Mon, 25 May 2026 10:03:03 GMT</pubDate>
            <atom:updated>2026-05-25T10:03:03.656Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_vTbKjrRKiiFC5zW" /><figcaption>Photo by <a href="https://unsplash.com/@vishnumaiea?utm_source=medium&amp;utm_medium=referral">Vishnu Mohanan</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>AI agents have become a normal part of my development workflow.</p><p>At first, I used them for small tasks: fixing a function, adding a test, cleaning up a README, or reviewing a small diff.</p><p>Over time, I started giving them larger chunks of work: reading an issue, making a plan, implementing the change, running tests, reviewing the result, and preparing a commit.</p><p><strong>The productivity gain was real.</strong></p><p>But while running a side project with increasingly agent-driven workflows, I started feeling a different kind of friction.</p><p>The more work I delegated to agents, the less visible the workflow became.</p><p>There is a big difference between “the agent is doing work” and “I understand and control how that work is happening.”</p><h4>Automation Was Powerful, but the Flow Was Hard to See</h4><p>A typical agent-assisted development routine often looks something like this:</p><pre>plan → implement → review → commit → merge → deploy</pre><p>But real project work is rarely that clean.</p><p>Sometimes review sends the work back to implementation. Sometimes I want to commit but not merge yet. Sometimes I need to check token usage between large steps.</p><p>The problem was that these flows were usually buried inside long prompts, terminal output, command history, and TUI sessions.</p><p><strong>I often found myself asking:</strong></p><ul><li>Which step is running now?</li><li>Which steps already finished?</li><li>Where did the workflow fail?</li><li>What is supposed to happen next?</li><li>Where should I intervene manually?</li></ul><p>The more useful the automation became, the harder it became to see the shape of the automation. That was the starting point for “<strong>Circuit”</strong>.</p><h3>What Is Circuit?</h3><h4><strong>4 key features</strong></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4EIUZQRXh4ttrq_O.png" /></figure><p>Circuit is a desktop app I made for building and running visual workflows from Claude and Codex skills.</p><p>It reads skills from a local repository, such as:</p><pre>.claude/skills/*/SKILL.md<br>.codex/skills/*/SKILL.md</pre><h4>1. Build Visual Skill Workflows</h4><p>Then it lets you place those skills on a canvas, connect them with dependencies, and run the workflow from one place.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FOpW5tIgsNPQ%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DOpW5tIgsNPQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FOpW5tIgsNPQ%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/136ef8cbcaa76974403800812cc3cc96/href">https://medium.com/media/136ef8cbcaa76974403800812cc3cc96/href</a></iframe><p>For example, you can build a flow like this:</p><pre>planning → implementation → review → commit</pre><p>If the routine changes, the graph can change with it:</p><pre>planning → implementation → commit → review</pre><p>If you need an extra check in the middle, you can add one:</p><pre>planning → check-token → implementation → review → wrap-up</pre><p>The goal is not just to run one skill. The goal is to turn repeated agent routines into visible, editable workflows.</p><h4>2. Use Claude And Codex Together</h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FdOEyMNWHeKQ%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdOEyMNWHeKQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FdOEyMNWHeKQ%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/bee40be36ba19137941265baecb35945/href">https://medium.com/media/bee40be36ba19137941265baecb35945/href</a></iframe><p>One thing I wanted to avoid was designing Circuit around a single agent runtime.</p><p>In real projects, agent automation is already mixed. Some workflows may exist as Claude skills. Others may be managed as Codex skills. Even within the same project, different tasks may benefit from different models or execution environments.</p><p>Circuit does not treat Claude and Codex as competing tools.</p><p>It treats them as different execution capabilities that belong to the same local project.</p><p>The actual skill files stay where they already live. Circuit does not move them into a new format or force a separate abstraction on top of them. It reads the existing skill files, shows them on the canvas, and provides a visual layer for defining order and dependencies.</p><h4>3. Track Execution State</h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FWaDQEdOp5oI%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DWaDQEdOp5oI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FWaDQEdOp5oI%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/507df42b05d211ccc98761726816b1c9/href">https://medium.com/media/507df42b05d211ccc98761726816b1c9/href</a></iframe><p>Designing a workflow is only half of the problem.</p><p>The other half is understanding what happens while it runs.</p><p>When a workflow runs in Circuit, the canvas and run log show which skill is currently running, which steps have completed, and where a failure happened.</p><p>That matters because agent work can otherwise feel like a black box. A long-running agent session may be doing exactly what you asked, but if you cannot see the current step or failure point, you still have to reconstruct the state from logs and prompts.</p><p>Circuit is meant to reduce that friction.</p><h4>4. Handle Loops</h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FrUCSjDn4dVI%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DrUCSjDn4dVI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FrUCSjDn4dVI%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/926a56f9d042e5c2d82b0b50d8307456/href">https://medium.com/media/926a56f9d042e5c2d82b0b50d8307456/href</a></iframe><p>Not every workflow is a straight line.</p><p>Some routines need repetition. A failed review might go back to implementation. A validation step might repeat until a condition is satisfied. A long workflow may need a check or compact step before continuing.</p><p>Circuit allows workflows with loops, but it treats them carefully.</p><p>Because a cyclic graph can run indefinitely, Circuit warns before execution and asks for explicit confirmation. The important part is that the loop is visible on the canvas. You can see which skill will run again and adjust the workflow before starting it.</p><p>The loop is not hidden inside a prompt or command chain.</p><h4>Closing Thought</h4><p>As AI agents become more capable, we will spend less time writing every line of code by hand.</p><p>But we will spend more time designing how agents work.</p><p>That workflow deserves a real interface.</p><p>Circuit is a small step in that direction: a visual harness for skill-based AI agent workflows, built from the friction I felt while running my own side project.</p><p>You can meet the Circuit in here</p><p><a href="https://github.com/CIrcui-try/Circuit#build-visual-skill-workflows">GitHub - CIrcui-try/Circuit: Skill-Based AI Agent Harness Editor</a></p><p>Thanks for reading!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=85865c1402ca" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Simplify Your SwiftUI Redirections in a Centralized Way]]></title>
            <link>https://enebin.medium.com/simplify-your-swiftui-redirections-in-a-centralized-way-5f782a53a007?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/5f782a53a007</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[network]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[swift-package-manager]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Sun, 23 Mar 2025 07:22:46 GMT</pubDate>
            <atom:updated>2025-03-23T07:22:46.053Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KcY4TCFL1GWlzFe9" /><figcaption>Photo by <a href="https://unsplash.com/@kindandcurious?utm_source=medium&amp;utm_medium=referral">Kind and Curious</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Managing URL redirections within SwiftUI applications often results in scattered, repetitive code, making maintenance cumbersome and error-prone.</p><p>Developers frequently face challenges in keeping redirection logic consistent and easily manageable across various parts of the app.</p><p>In this post, I’ll share how to achieve centralized URL management effortlessly using SwiftUI, making your applications cleaner and easier to maintain.</p><h4><strong>Quick promo </strong>🔊</h4><p>I’ve created a lightweight Swift package to simplify this process. If you’re interested, please check out the GitHub repo:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ib_-7J6olS1n78tK.png" /></figure><p><a href="https://github.com/enebin/ShopIt">GitHub - enebin/ShopIt: One line, one tap. Redirect with ShopIt</a></p><h3>The Problem with SwiftUI URL Redirection</h3><p>Typically, developers handle URL redirection individually within views, often duplicating logic and cluttering the view layer.</p><p>This scattered approach means every button or interactive element that requires redirection must handle its own logic independently, leading to repetitive boilerplate and increased chances of errors.</p><p>Consider a button triggering a redirect;</p><pre>@Environment(\.openURL) private var openURL<br>Button(&quot;Redirect&quot;) {<br>    openURL(schemeLink) { accepted in<br>        if !accepted {<br>            openURL(webLink) { accepted in<br>                if !accepted {<br>                    print(&quot;🚨 Unable to redirect to the web page&quot;)<br>                }<br>            }<br>        }<br>    }<br>}</pre><p>This approach scatters URL management logic throughout the app, increasing complexity.</p><h3>Introducing a Centralized Approach</h3><p>My solution employs clearly defined abstractions (Redirectable) and reusable components (RedirectButton) that encapsulate the redirection logic into a single place.</p><p>This significantly simplifies implementation, boosts consistency, and eases future updates.</p><h4>Core Components</h4><p><strong>1. </strong><strong>Redirectable Protocol</strong></p><p>Defines the necessary properties for redirection:</p><pre><br>public protocol SchemeRedirectable {<br>   var schemeUrl: QueryableURL { get }<br>}<br>public protocol WebRedirectable {<br>   var webUrl: QueryableURL { get }<br>}<br><br>public protocol Redirectable: SchemeRedirectable &amp; WebRedirectable {}</pre><p>2<strong>. </strong><strong>QueryableURL Struct</strong></p><p>Manages URL creation with dynamic queries, ensuring safer and more flexible URL handling:</p><pre>public struct QueryableURL {<br>    public let baseURL: URL<br>    public let queryBuilder: (String) -&gt; [URLQueryItem]<br>    public func url(with keyword: String) -&gt; URL? {<br>        guard var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false) else {<br>            return nil<br>        }<br>        <br>        let newQueryItems = queryBuilder(keyword)<br>        components.queryItems = (components.queryItems ?? []) + newQueryItems<br>        <br>        return components.url<br>    }<br>}</pre><p><strong>3. </strong><strong>Redirector</strong></p><p>The Redirector class handles URL redirection logic centrally, automatically managing scheme URLs with seamless fallback to web URLs:</p><pre>public final class Redirector {<br>    public private(set) var openUrlAction: OpenURLAction?<br><br>    public func register(_ opener: OpenURLAction) { openUrlAction = opener }<br><br>    public func redirect(keyword: String, to redirection: some Redirectable) async throws {<br>        let primary = redirection.schemeUrl<br>        let fallback = redirection.webUrl<br>        <br>        do { try await openLink(using: primary, keyword: keyword) }<br>        catch { try await openLink(using: fallback, keyword: keyword) }<br>    }<br>}<br><br><br>private extension Redirector {<br>    func openLink(using queryable: QueryableURL, keyword: String) async throws {<br>        guard let url = queryable.url(with: keyword) else {<br>            throw Error.invalidURL<br>        }<br>        <br>        try await performOpenUrlAction(url)<br>    }<br>    <br>    func performOpenUrlAction(_ url: URL) async throws  {<br>        guard let openUrlAction else {<br>            throw Error.openUrlActionNotSet<br>        }<br>        <br>        return try await withCheckedThrowingContinuation { continuation in<br>            Task { @MainActor in<br>                openUrlAction(url) { accepted in<br>                    if accepted {<br>                        continuation.resume(returning: ())<br>                    } else {<br>                        continuation.resume(throwing: Error.cannotOpenURL)<br>                    }<br>                }<br>            }<br>        }<br>    }<br>}</pre><p>Don’t forget to register openURL when use this. The reason it’s registered externally rather than declared directly here is because openURL must be called within the context of a SwiftUI View.</p><p>Also, you can add a flag such as redirectPriority to adjust the priority between web and scheme links according to your needs.</p><p><strong>4. </strong><strong>RedirectButton View</strong></p><p>A reusable button component that encapsulates the redirection logic cleanly within the view layer:</p><pre><br>public struct RedirectButton&lt;Content, Redirection&gt;: View<br>where Content: View, Redirection: Redirectable {<br>    @Environment(\.openURL) private var openURL<br><br>    private let content: () -&gt; Content<br>    private let keyword: String<br>    private let redirection: Redirection<br>    <br>    public init(keyword: String, redirection: Redirection, @ViewBuilder content: @escaping () -&gt; Content) {<br>        self.content = content<br>        self.keyword = keyword<br>        self.redirection = redirection<br>    }<br>    <br>    public var body: some View {<br>        Button(<br>            action: {<br>                Task {<br>                    do {<br>                        try await Redirector.shared.redirect(keyword: keyword, to: redirection)<br>                    }catch {<br>                        print(&quot;🚨 Error occurs: \(error.localizedDescription)&quot;)<br>                    }<br>                }<br>            },<br>            label: content<br>        )<br>        .task {<br>            if redirector.openUrlAction == nil {<br>                redirector.register(openURL)<br>            }<br>        }<br>    }<br>}</pre><p><strong>4. </strong><strong>RedirectButton View</strong></p><p>RedirectButton encapsulates URL redirection logic by leveraging the ShopitRedirector, simplifying its usage within the view layer:</p><pre>public struct RedirectButton&lt;Content, Redirection&gt;: View<br>where Content: View, Redirection: Redirectable {<br>    @Environment(\.openURL) private var openURL<br><br>    private let content: () -&gt; Content<br>    private let keyword: String<br>    private let redirection: Redirection<br><br>    public var body: some View {<br>        Button {<br>            Task { try await redirector.redirect(keyword: keyword, to: redirection) }<br>        } label: {<br>            content()<br>        }<br>        .task {<br>            if redirector.openUrlAction == nil {<br>                redirector.register(openURL)<br>            }<br>        }<br>    }<br>}</pre><h3>Practical Example: Google Search</h3><p>With this structured approach, adding redirection buttons to your SwiftUI views becomes extremely straightforward and consistent:</p><pre>public struct GoogleSearchRedirection: Redirectable {<br>    public let schemeUrl = QueryableURL(baseURL: URL(string: &quot;google://search&quot;)!) { [URLQueryItem(name: &quot;q&quot;, value: $0)] }<br>    public let webUrl = QueryableURL(baseURL: URL(string: &quot;https://www.google.com/search&quot;)!) { [URLQueryItem(name: &quot;q&quot;, value: $0)] }<br>}<br><br>RedirectButton(keyword: &quot;iPhone&quot;, redirection: .googleSearch) {<br>    Text(&quot;Search iPhone on Google!&quot;)<br>}<br>.buttonStyle(.borderedProminent)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/295/1*EFVyFO9tQ2Kn9bGw4hNOKw.gif" /></figure><p>With this centralized structure, implementing new redirections becomes straightforward and error-resistant.</p><h3>Conclusion</h3><p>Centralizing URL redirections with SwiftUI reduces complexity, minimizes errors, and significantly improves app maintainability and scalability.</p><p>Integrate this approach into your next SwiftUI project for smoother, more efficient URL handling!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5f782a53a007" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Create Facial Expressions Recognition on iOS: A Step-by-Step Guide]]></title>
            <link>https://enebin.medium.com/how-to-create-facial-expressions-recognition-on-ios-a-step-by-step-guide-7f1640c1db5c?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/7f1640c1db5c</guid>
            <category><![CDATA[mls]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Thu, 27 Jun 2024 12:02:50 GMT</pubDate>
            <atom:updated>2024-06-27T12:03:46.820Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dqb0ktrxcMcNyfJ5" /><figcaption>Photo by <a href="https://unsplash.com/@timmossholder?utm_source=medium&amp;utm_medium=referral">Tim Mossholder</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>In today’s tech-savvy world, creating apps that understand human emotions is within reach. Facial expressions recognition, powered by Apple’s Core ML and Vision frameworks, allows your iOS apps to interpret users’ emotions from their facial cues.</p><p>This guide will take you step-by-step through building this innovative feature, making it easy to add emotional intelligence to your applications.</p><p>Whether you’re an experienced developer or a beginner, you’ll learn how to create more engaging and responsive apps with facial expressions recognition on iOS. Let’s get started!</p><p>Before that, I have already created a Swift Package that compresses the tedious process ahead, making it easy to use.</p><p><strong>You can use the facial expression reconition with just a single line of code! </strong>It also fully supports UIImage, CGImage and SwiftUI’s Image<strong>. </strong>If you want to quickly utilize this feature, try using this package 😉</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rE758vOnYMW_xmagSDgz9g.png" /></figure><p><a href="https://github.com/enebin/Mentalist">GitHub - enebin/Mentalist: Read face with a line of code 🎭</a></p><h3><strong>Step 1: Converting a .h5 file to a CoreML Model</strong></h3><p>To integrate facial expressions recognition into your iOS app, the first step is converting your Python-trained model (in .h5 format) to a CoreML model. Here’s how:</p><ol><li><strong>Set Up Environment</strong>:</li></ol><ul><li>Install Python and the necessary libraries: coremltools and tensorflow or keras.</li></ul><p>2. <strong>Load the h5 Model</strong>:</p><ul><li>Use TensorFlow or Keras to load your trained h5 model.</li><li>In this post, we will the pre-trained weights(facial_expression_model_weights.h5) from <a href="https://github.com/serengil/deepface_models/releases">Deepface</a> which has 57% of accuracy with FER2013.</li></ul><p>3. <strong>Convert to CoreML</strong>:</p><ul><li>Utilize coremltools to convert your h5 model, specifying input and output layers.</li></ul><p>4. <strong>Save the CoreML Model</strong>:</p><ul><li>Save the converted model with a .mlmodel extension.</li></ul><p>This part is slightly beyond the scope of iOS development. I have provided the code below that can be used here, so please review and run it yourself. By doing so, you will be able to obtain the CoreML model.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cade589aa2ace864ca2c3cdbf244d92d/href">https://medium.com/media/cade589aa2ace864ca2c3cdbf244d92d/href</a></iframe><h3><strong>Step 2: Preprocessing and Handling Images</strong></h3><p>To effectively recognize facial expressions, it is crucial to preprocess the images. This step involves converting images to a suitable format and preparing them for analysis. Here’s how to do it on iOS using Swift:</p><ol><li><strong>Convert to Grayscale</strong></li></ol><ul><li>Grayscale images simplify the processing and reduce computational load. Use Core Image filters to convert the image to grayscale.</li></ul><p>2. <strong>Resize Image</strong></p><ul><li>Resize the image to a standard size (e.g., 48x48 pixels). This ensures uniformity and makes the model’s job easier.</li></ul><p>3. <strong>Normalize Image</strong></p><ul><li>Normalize the pixel values to a range suitable for the model (typically 0 to 1). This helps in improving the model’s accuracy.</li></ul><p>4. <strong>Face Detection</strong></p><ul><li>Detect faces within the image using Vision framework’s face detection capabilities.</li></ul><p>5. <strong>Crop Faces</strong></p><ul><li>Crop the detected face regions from the image for further analysis.</li></ul><p>Here’s the Swift code implementing these steps:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/70223429c418b50c5845c209e7b9b908/href">https://medium.com/media/70223429c418b50c5845c209e7b9b908/href</a></iframe><h3><strong>Step 3: Passing the Image to CoreML for Analysis</strong></h3><p>Once the image is preprocessed, the next step is to pass it to your CoreML model for facial expression analysis.</p><p>This involves loading the CoreML model, detecting faces, preprocessing each face, and then using the model to analyze the emotions. Here’s how to do it:</p><ol><li><strong>Initialize the CoreML Model</strong></li></ol><ul><li>Load your CoreML model using the VNCoreMLModel class.</li></ul><p>2. <strong>Detect Faces</strong></p><ul><li>Use the FaceImageTool to detect faces in the input image.</li></ul><p>3. <strong>Preprocess Each Face</strong></p><ul><li>For each detected face, crop and preprocess the face image to prepare it for the model.</li></ul><p>4. <strong>Perform Emotion Analysis</strong></p><ul><li>Pass the preprocessed face image to the CoreML model for emotion analysis.</li><li>Extract and interpret the results from the model’s output.</li></ul><p>Here’s the Swift code implementing these steps:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d07fcc92c7d133f009b01483945216f0/href">https://medium.com/media/d07fcc92c7d133f009b01483945216f0/href</a></iframe><h3><strong>Done!</strong></h3><p>All you need to do is create the MLCore and provide it with a picture of a person making a facial expression like:</p><pre>let analysis = MLCore().analyze(uiImage: UIImage(&quot;some_face&quot;)?.cgImage)<br>print(analysis.map { $0.dominantEmotion })<br>// [happy, sad]</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7f1640c1db5c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Designing a better UIViewControllerRepresentable [2] — Without @Binding]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://enebin.medium.com/designing-a-better-uiviewcontrollerrepresentable-2-without-binding-ea9b167cce93?source=rss-84589cdcce2f------2"><img src="https://cdn-images-1.medium.com/max/2600/0*w4IhzI72AF7Tdlaf" width="6613"></a></p><p class="medium-feed-snippet">In the previous post, we examined the simplest method using @Binding. However, as mentioned before, the main downside to this approach is&#x2026;</p><p class="medium-feed-link"><a href="https://enebin.medium.com/designing-a-better-uiviewcontrollerrepresentable-2-without-binding-ea9b167cce93?source=rss-84589cdcce2f------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://enebin.medium.com/designing-a-better-uiviewcontrollerrepresentable-2-without-binding-ea9b167cce93?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/ea9b167cce93</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[iphone]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[uikit]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Wed, 01 May 2024 08:49:54 GMT</pubDate>
            <atom:updated>2024-05-01T08:49:54.160Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Designing a better UIViewControllerRepresentable [1] — Basic]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://enebin.medium.com/mastering-updates-and-debugging-in-uiviewcontrollerrepresentable-1-basic-68fff5b30aa1?source=rss-84589cdcce2f------2"><img src="https://cdn-images-1.medium.com/max/2600/0*gNStejFPi9i01cGi" width="6613"></a></p><p class="medium-feed-snippet">In order to convert UIKit components into SwiftUI, you must use a specific API, UIView(Controller)Representable. As many who have used&#x2026;</p><p class="medium-feed-link"><a href="https://enebin.medium.com/mastering-updates-and-debugging-in-uiviewcontrollerrepresentable-1-basic-68fff5b30aa1?source=rss-84589cdcce2f------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://enebin.medium.com/mastering-updates-and-debugging-in-uiviewcontrollerrepresentable-1-basic-68fff5b30aa1?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/68fff5b30aa1</guid>
            <category><![CDATA[iphone]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[swiftui]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Tue, 30 Apr 2024 12:01:31 GMT</pubDate>
            <atom:updated>2024-05-01T08:51:26.513Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Real World Design Pattern for iOS [6] — Prototype]]></title>
            <link>https://enebin.medium.com/real-world-design-pattern-for-ios-6-prototype-f448ccf5fc9e?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/f448ccf5fc9e</guid>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Wed, 24 Apr 2024 10:23:18 GMT</pubDate>
            <atom:updated>2024-04-24T10:23:18.928Z</atom:updated>
            <content:encoded><![CDATA[<h3>Real World Design Pattern for iOS [6] — Prototype</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CK5AxmDbyDAL_sxt" /><figcaption>Photo by <a href="https://unsplash.com/@dialex?utm_source=medium&amp;utm_medium=referral">Diogo Nunes</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>What is Prototype pattern?</h3><p>The Prototype pattern is a creational design pattern that lets you copy existing objects without making your code dependent on their classes. It involves three key components:</p><h4>Prototype Interface</h4><p>This interface declares the methods for cloning itself. The interface ensures that all prototypes can be cloned interchangeably.</p><h4>Concrete Prototypes</h4><p>These are classes that implement the prototype interface and define the method to clone themselves. Each offers a different way of performing a cloning operation based on their internal states.</p><h4>Client</h4><p>An object that holds a reference to a prototype and delegates the cloning process to the prototype. The client can dynamically choose among different prototypes to clone, depending on the runtime requirements.</p><h3>Why should we use it?</h3><p>This pattern is useful for scenarios where object creation is costly or complex but a similar object already exists. It helps keep the system flexible and maintainable by enabling objects to produce their copies. This avoids coupling to the concrete classes of objects that need to be copied.</p><p>It follows the open/closed principle by allowing new object types to be introduced with minimal changes to the existing code.</p><h3>Real World Examples</h3><h4>1. Document Management System</h4><p>Imagine a system where documents can be created and edited. A user might want to make a copy of an existing document to use as a base for a new document without starting from scratch.</p><ul><li><strong>Prototype Interface</strong>: DocumentPrototype</li><li><strong>Concrete Prototypes</strong>: TextDocument, SpreadsheetDocument</li><li><strong>Client</strong>: The application interface or document manager that creates duplicates of documents.</li></ul><pre><br>// Prototype Interface<br>protocol DocumentPrototype {<br>     func clone() -&gt; DocumentPrototype<br>}<br><br>// Concrete Prototypes<br>class TextDocument: DocumentPrototype {<br>     var content: String<br>     <br>     init(content: String) {<br>         self.content = content<br>         }<br>     <br>     func clone() -&gt; DocumentPrototype {<br>         return TextDocument(content: self.content)<br>         }<br>}<br>class SpreadsheetDocument: DocumentPrototype {<br>     var data: [[Int]]<br>     <br>     init(data: [[Int]]) {<br>         self.data = data<br>         }<br>     <br>     func clone() -&gt; DocumentPrototype {<br>         return SpreadsheetDocument(data: self.data)<br>         }<br>}<br><br>// Client<br>class DocumentManager {<br>     private var documents: [DocumentPrototype] = []<br>     <br>     func addDocument(_ document: DocumentPrototype) {<br>         documents.append(document)<br>         }<br>     <br>     func cloneDocument(at index: Int) -&gt; DocumentPrototype? {<br>         guard index &lt; documents.count else { return nil }<br>         return documents[index].clone()<br>         }<br>}<br><br>// Usage<br>let textDoc = TextDocument(content: &quot;Initial content&quot;)<br>let spreadsheet = SpreadsheetDocument(data: [[1, 2], [3, 4]])<br>let manager = DocumentManager()<br>manager.addDocument(textDoc)<br>manager.addDocument(spreadsheet)<br><br>if let clonedTextDoc = manager.cloneDocument(at: 0) as? TextDocument {<br>     print(&quot;Cloned Text Document Content: \(clonedTextDoc.content)&quot;)<br>}<br>if let clonedSheet = manager.cloneDocument(at: 1) as? SpreadsheetDocument {<br>     print(&quot;Cloned Spreadsheet Data: \(clonedSheet.data)&quot;)<br>}</pre><h4>2. Game Character Generation</h4><p>In a game where new characters can be spawned based on existing ones — each with potentially unique attributes (like health, strength, etc.) — the Prototype pattern allows for easy character duplication with modifications.</p><ul><li><strong>Prototype Interface</strong>: GameCharacter</li><li><strong>Concrete Prototypes</strong>: Hero, Villain</li><li><strong>Client</strong>: The game environment or character manager.</li></ul><pre>// Prototype Interface<br>protocol GameCharacter {<br>     func clone() -&gt; GameCharacter<br>     var health: Int { get set }<br>}<br><br>// Concrete Prototypes<br>class Hero: GameCharacter {<br>     var health: Int<br>     <br>     init(health: Int) {<br>         self.health = health<br>         }<br>     <br>     func clone() -&gt; GameCharacter {<br>         return Hero(health: self.health)<br>         }<br>}<br>class Villain: GameCharacter {<br>     var health: Int<br>     <br>     init(health: Int) {<br>         self.health = health<br>         }<br>     <br>     func clone() -&gt; GameCharacter {<br>         return Villain(health: self.health)<br>         }<br>}<br><br>// Client<br>class GameEnvironment {<br>     private var characters: [GameCharacter] = []<br>     <br>     func addCharacter(_ character: GameCharacter) {<br>         characters.append(character)<br>         }<br>     <br>     func cloneCharacter(at index: Int) -&gt; GameCharacter? {<br>         guard index &lt; characters.count else { return nil }<br>         return characters[index].clone()<br>         }<br>}<br><br>// Usage<br>let hero = Hero(health: 100)<br>let villain = Villain(health: 150)<br>let game = GameEnvironment()<br>game.addCharacter(hero)<br>game.addCharacter(villain)<br><br>if let clonedHero = game.cloneCharacter(at: 0) {<br>     print(&quot;Cloned Hero Health: \(clonedHero.health)&quot;)<br>}<br>if let clonedVillain = game.cloneCharacter(at: 1) {<br>     print(&quot;Cloned Villain Health: \(clonedVillain.health)&quot;)<br>}</pre><p><a href="https://en.wikipedia.org/wiki/Prototype_pattern">Prototype pattern - Wikipedia</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f448ccf5fc9e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Real World Design Pattern for iOS [5] — Adaptor]]></title>
            <link>https://enebin.medium.com/real-world-design-pattern-for-ios-5-adaptor-4dd157eec4a5?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/4dd157eec4a5</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[uikit]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Mon, 22 Apr 2024 13:27:01 GMT</pubDate>
            <atom:updated>2024-04-24T10:18:57.825Z</atom:updated>
            <content:encoded><![CDATA[<h3>Real World Design Pattern for iOS [5] — Adaptor</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*C9CmJSCvf2MGf51A" /><figcaption>Photo by <a href="https://unsplash.com/@dialex?utm_source=medium&amp;utm_medium=referral">Diogo Nunes</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>What is Adpator pattern?</h3><p>The Adapter pattern is a structural design pattern that allows objects with incompatible interfaces to work together by converting the interface of one class into an interface expected by the clients. It involves three key components.</p><h4>Target Interface</h4><p>This is the common interface that the client expects to work with. It defines the domain-specific operations which the client understands.</p><h4>Adapter</h4><p>This is the class that implements the target interface and wraps the adaptee. The adapter translates the interface of the adaptee class into an interface that the client expects.</p><h4>Adaptee</h4><p>This is the class that has the existing interface but needs adapting before the client can use it.</p><h3>Why should we use it?</h3><p>This pattern is useful in scenarios where you want to reuse existing classes that do not have interfaces that are compatible with the other parts of an application.</p><p>It helps keep the system flexible and maintainable by enabling classes with differing interfaces to communicate and work together, thereby promoting reusability and preventing changes to existing code while introducing new interface implementations. This is aligned with the open/closed principle of software design, which promotes extension but discourages modification.</p><h3>Real World Example</h3><h4>1: Legacy Database Integration</h4><p>Suppose you are working on a modern application that needs to integrate with a legacy system. The legacy system provides data in a format that the new system cannot directly consume.</p><ul><li><strong>Target Interface</strong>: NewDatabase</li><li>Adapter: LegacyDatabaseAdapter</li><li>Adaptee: LegacyDatabase</li></ul><pre>protocol NewDatabase {<br>     func fetchData() -&gt; [String]<br>}<br><br>class LegacyDatabase {<br>     func retrieveData() -&gt; [String] {<br>         return [&quot;Data1&quot;, &quot;Data2&quot;, &quot;Data3&quot;]<br>         }<br>}<br><br>class LegacyDatabaseAdapter: NewDatabase {<br>     private let legacyDatabase: LegacyDatabase<br>     <br>     init(_ legacyDatabase: LegacyDatabase) {<br>         self.legacyDatabase = legacyDatabase<br>         }<br>     <br>     func fetchData() -&gt; [String] {<br>         return legacyDatabase.retrieveData() // Adapting data retrieval<br>     }<br>}<br><br>// Client code<br>let legacyDB = LegacyDatabase()<br>let adapter = LegacyDatabaseAdapter(legacyDB)<br>let data = adapter.fetchData()<br><br>print(data)</pre><h4>2. Third-party API Integration</h4><p>Imagine integrating a third-party library that logs detailed analytics but your application’s logging interface is not compatible with the library’s methods.</p><ul><li><strong>Target Interface</strong>: ApplicationLogger</li><li><strong>Adapter</strong>: AnalyticsLoggerAdapter</li><li><strong>Adaptee</strong>: ThirdPartyAnalytics</li></ul><pre><br>protocol ApplicationLogger {<br>     func log(message: String)<br>}<br><br>class ThirdPartyAnalytics {<br>     func sendAnalyticsEvent(info: [String: Any]) {<br>         print(&quot;Analytics Event: \(info)&quot;)<br>     }<br>}<br><br>class AnalyticsLoggerAdapter: ApplicationLogger {<br>     private var analytics: ThirdPartyAnalytics<br>     <br>     init(analytics: ThirdPartyAnalytics) {<br>         self.analytics = analytics<br>     }<br>     <br>     func log(message: String) {<br>         analytics.sendAnalyticsEvent(info: [&quot;event&quot;: message])<br>     }<br>}<br><br>// Client code<br>let analytics = ThirdPartyAnalytics()<br>let logger = AnalyticsLoggerAdapter(analytics: analytics)<br>logger.log(message: &quot;User logged in&quot;)</pre><p><a href="https://en.wikipedia.org/wiki/Adapter_pattern">Adapter pattern - Wikipedia</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4dd157eec4a5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Real World Design Pattern for iOS [4] — Factory]]></title>
            <link>https://enebin.medium.com/real-world-design-pattern-for-ios-4-factory-9e9f13b9a235?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/9e9f13b9a235</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[design-patterns]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Tue, 02 Apr 2024 10:36:31 GMT</pubDate>
            <atom:updated>2024-04-02T10:36:31.019Z</atom:updated>
            <content:encoded><![CDATA[<h3>Real World Design Pattern for iOS [4] — Factory</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*MkxmoDOJgdmbYl2V" /><figcaption>Photo by <a href="https://unsplash.com/@dialex?utm_source=medium&amp;utm_medium=referral">Diogo Nunes</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>What is Factory pattern?</h3><p>The Factory pattern is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. It involves three key components:</p><h4>Factory Interface</h4><p>A common interface for creating objects. This interface defines a method for creating objects, but it’s up to the concrete factory classes to specify which class to instantiate.</p><h4>Concrete Factories</h4><p>Implementations of the factory interface. Each concrete factory is responsible for creating objects of a specific type. These factories instantiate objects based on the logic and criteria they encapsulate.</p><h4>Products</h4><p>The objects being created. All products follow a common interface or abstract class, and the factory’s method returns an object of this type. However, the concrete class of the object instantiated by the factory method is determined by the concrete factory.</p><h3>Why should we use it</h3><p>This pattern is useful when the exact types and dependencies of the objects your code should work with are not known in advance or when you want to provide a way to extend and modify created objects without changing existing code.</p><p>It promotes loose coupling by reducing the dependency of client classes on concrete classes, adhering to the open/closed principle of software design by allowing the system to be easily extended with new types of objects.</p><h3>Real World Examples</h3><h4>1. Document Management System</h4><p>Imagine a document management application that supports different types of documents, such as Text Documents, Spreadsheets, and Presentations.</p><p>Each document type has its own properties and behaviors but shares common functionalities like save, edit, and render. Using the Factory pattern, we can streamline the creation of these documents while keeping our system flexible and scalable.</p><ul><li><strong>Factory Interface</strong>: DocumentFactory</li><li><strong>Concrete Factories</strong>: TextDocumentFactory, SpreadsheetFactory, PresentationFactory</li><li><strong>Products</strong>: Document, TextDocument, Spreadsheet, Presentation</li></ul><pre>// Product Interface<br>protocol Document {<br>    func save()<br>    func edit()<br>    func render()<br>}<br><br>// Concrete Products<br>class TextDocument: Document {<br>    func save() { print(&quot;Saving TextDocument&quot;) }<br>    func edit() { print(&quot;Editing TextDocument&quot;) }<br>    func render() { print(&quot;Rendering TextDocument&quot;) }<br>}<br><br>class Spreadsheet: Document {<br>    func save() { print(&quot;Saving Spreadsheet&quot;) }<br>    func edit() { print(&quot;Editing Spreadsheet&quot;) }<br>    func render() { print(&quot;Rendering Spreadsheet&quot;) }<br>}<br><br>class Presentation: Document {<br>    func save() { print(&quot;Saving Presentation&quot;) }<br>    func edit() { print(&quot;Editing Presentation&quot;) }<br>    func render() { print(&quot;Rendering Presentation&quot;) }<br>}<br><br>// Factory Interface<br>protocol DocumentFactory {<br>    func createDocument() -&gt; Document<br>}<br><br>// Concrete Factories<br>class TextDocumentFactory: DocumentFactory {<br>    func createDocument() -&gt; Document {<br>        return TextDocument()<br>    }<br>}<br><br>class SpreadsheetFactory: DocumentFactory {<br>    func createDocument() -&gt; Document {<br>        return Spreadsheet()<br>    }<br>}<br><br>class PresentationFactory: DocumentFactory {<br>    func createDocument() -&gt; Document {<br>        return Presentation()<br>    }<br>}<br><br>// Client code<br>func clientCode(factory: DocumentFactory) {<br>    let document = factory.createDocument()<br>    document.edit()<br>    document.save()<br>    document.render()<br>}<br><br>// Usage<br>let textFactory = TextDocumentFactory()<br>clientCode(factory: textFactory)<br><br>let spreadsheetFactory = SpreadsheetFactory()<br>clientCode(factory: spreadsheetFactory)<br><br>let presentationFactory = PresentationFactory()<br>clientCode(factory: presentationFactory)</pre><h4>2. Payment Gateway Integration for an E-commerce Platform</h4><p>Imagine an e-commerce platform that needs to integrate multiple payment gateways to process transactions. Different payment gateways (like PayPal, Stripe, and Square) have their unique APIs and integration processes.</p><p>Using the Factory pattern, the platform can simplify the integration process, making it easier to add or switch payment gateways without affecting the core payment processing logic.</p><ul><li><strong>Factory Interface</strong>: PaymentGatewayFactory</li><li><strong>Concrete Factories</strong>: PayPalFactory, StripeFactory, SquareFactory</li><li><strong>Products</strong>: PaymentGateway, which defines the common interface for all payment operations.</li></ul><pre>// Product Interface<br>protocol PaymentGateway {<br>    func authenticate()<br>    func makePayment(amount: Double)<br>}<br><br>// Concrete Products<br>class PayPal: PaymentGateway {<br>    func authenticate() { print(&quot;Authenticating with PayPal&quot;) }<br>    func makePayment(amount: Double) { print(&quot;Paying \(amount) using PayPal&quot;) }<br>}<br><br>class Stripe: PaymentGateway {<br>    func authenticate() { print(&quot;Authenticating with Stripe&quot;) }<br>    func makePayment(amount: Double) { print(&quot;Paying \(amount) using Stripe&quot;) }<br>}<br><br>class Square: PaymentGateway {<br>    func authenticate() { print(&quot;Authenticating with Square&quot;) }<br>    func makePayment(amount: Double) { print(&quot;Paying \(amount) using Square&quot;) }<br>}<br><br>// Factory Interface<br>protocol PaymentGatewayFactory {<br>    func createPaymentGateway() -&gt; PaymentGateway<br>}<br><br>// Concrete Factories<br>class PayPalFactory: PaymentGatewayFactory {<br>    func createPaymentGateway() -&gt; PaymentGateway {<br>        return PayPal()<br>    }<br>}<br><br>class StripeFactory: PaymentGatewayFactory {<br>    func createPaymentGateway() -&gt; PaymentGateway {<br>        return Stripe()<br>    }<br>}<br><br>class SquareFactory: PaymentGatewayFactory {<br>    func createPaymentGateway() -&gt; PaymentGateway {<br>        return Square()<br>    }<br>}<br><br>// Client code<br>func processPayment(factory: PaymentGatewayFactory, amount: Double) {<br>    let paymentGateway = factory.createPaymentGateway()<br>    paymentGateway.authenticate()<br>    paymentGateway.makePayment(amount: amount)<br>}<br><br>// Usage<br>let amountToPay = 99.99<br>processPayment(factory: PayPalFactory(), amount: amountToPay)<br>processPayment(factory: StripeFactory(), amount: amountToPay)<br>processPayment(factory: SquareFactory(), amount: amountToPay)</pre><p><a href="https://en.wikipedia.org/wiki/Factory_method_pattern">Factory method pattern - Wikipedia</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e9f13b9a235" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Real World Design Pattern for iOS [3] — Builder]]></title>
            <link>https://enebin.medium.com/real-world-design-pattern-for-ios-2-builder-4aed8093887b?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/4aed8093887b</guid>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Sat, 23 Mar 2024 23:31:55 GMT</pubDate>
            <atom:updated>2024-04-29T10:00:49.639Z</atom:updated>
            <content:encoded><![CDATA[<h3>Real World Design Pattern for iOS [3] — Builder</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ZtjLVKbho2Grjkub" /><figcaption>Photo by <a href="https://unsplash.com/@dialex?utm_source=medium&amp;utm_medium=referral">Diogo Nunes</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>What is Builder pattern?</h3><p>The Builder pattern is a design pattern that separates the construction of a complex object from its representation, allowing the same construction process to create different representations.</p><p>It involves four key components:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/460/0*Lpuh49Rl1IowSLIQ.png" /><figcaption>Image from <a href="https://refactoring.guru/design-patterns/builder">Builder (refactoring.guru)</a></figcaption></figure><h4>Builder Interface</h4><p>A common interface for building parts of a complex object. It defines the steps needed to build the object.</p><h4>Concrete Builders</h4><p>Implementations of the builder interface, each constructing and assembling parts of the product differently.</p><h4>Director</h4><p>An object that knows how to compose a complex object using the builder interface. It controls the construction process.</p><h4>Product</h4><p>The complex object that is being built. The final product constructed by the concrete builders, often with varying representations.</p><h3>Why should we use it?</h3><p>This pattern is useful for scenarios where a<strong> system needs to create complex objects that are composed of many parts</strong> or<strong> require an elaborate construction process</strong>.</p><ul><li>It provides flexibility in the construction process, allowing the creation of various representations of a product using the same construction code.</li><li>By decoupling the construction of a complex object from its representation, the Builder pattern enables more control over the construction process and supports the construction of complex composite objects.</li></ul><h3>Real World Examples</h3><h4>1. Ordering a Customized Computer</h4><ul><li>Builder Interface: ComputerBuilder</li><li>Concrete Builders: GamingComputerBuilder, OfficeComputerBuilder, GraphicDesignComputerBuilder</li><li>Director: ComputerShop</li><li>Product: Computer</li></ul><pre>// Builder Interface<br>protocol ComputerBuilder {<br>    func setCPU(_ cpu: String)<br>    func setGPU(_ gpu: String)<br>    func setMemory(_ memory: String)<br>    func build() -&gt; Computer<br>}<br><br>// Concrete Builders<br>class GamingComputerBuilder: ComputerBuilder {<br>    private var computer = Computer()<br>    <br>    func setCPU(_ cpu: String) {<br>        computer.cpu = cpu<br>    }<br>    <br>    func setGPU(_ gpu: String) {<br>        computer.gpu = gpu<br>    }<br>    <br>    func setMemory(_ memory: String) {<br>        computer.memory = memory<br>    }<br>    <br>    func build() -&gt; Computer {<br>        return computer<br>    }<br>}<br><br>// Similar implementations for OfficeComputerBuilder and GraphicDesignComputerBuilder...<br><br>// Product<br>class Computer {<br>    var cpu: String?<br>    var gpu: String?<br>    var memory: String?<br>    <br>    func describe() {<br>        print(&quot;Computer with CPU: \(cpu ?? &quot;N/A&quot;), GPU: \(gpu ?? &quot;N/A&quot;), Memory: \(memory ?? &quot;N/A&quot;)&quot;)<br>    }<br>}<br><br>// Director<br>class ComputerShop {<br>    private var builder: ComputerBuilder?<br>    <br>    func constructGamingComputer(builder: ComputerBuilder) {<br>        self.builder = builder<br>        builder.setCPU(&quot;High-end CPU&quot;)<br>        builder.setGPU(&quot;High-end GPU&quot;)<br>        builder.setMemory(&quot;32GB&quot;)<br>    }<br>    <br>    // Similar methods for constructOfficeComputer and constructGraphicDesignComputer...<br>    <br>    func getComputer() -&gt; Computer? {<br>        return builder?.build()<br>    }<br>}<br><br>// Usage<br>let shop = ComputerShop()<br>let gamingBuilder = GamingComputerBuilder()<br><br>shop.constructGamingComputer(builder: gamingBuilder)<br>let gamingComputer = shop.getComputer()<br>gamingComputer?.describe()<br>// Output: Computer with CPU: High-end CPU, GPU: High-end GPU, Memory: 32GB</pre><ul><li>In this example, the ComputerBuilder protocol defines the steps necessary for building a computer.</li><li>This approach allows customers to customize their computer with different components while the construction process is abstracted away by the builder pattern, making the system flexible and maintainable.</li></ul><h4>2. Building a User Profile in a Social Media App</h4><ul><li>Builder Interface: UserProfileBuilder</li><li>Concrete Builder: UserProfileConcreteBuilder</li><li>Director: (In this simplified example, we’ll use the builder directly without a director)</li><li>Product: UserProfile</li></ul><pre>// Product<br>class UserProfile {<br>    var username: String<br>    var biography: String?<br>    var location: String?<br>    var interests: [String] = []<br>    var profilePictureURL: String?<br>    <br>    init(username: String) {<br>        self.username = username<br>    }<br>    <br>    func describe() {<br>        print(&quot;UserProfile(username: \(username), biography: \(biography ?? &quot;N/A&quot;), location: \(location ?? &quot;N/A&quot;), interests: \(interests.joined(separator: &quot;, &quot;)), profilePictureURL: \(profilePictureURL ?? &quot;N/A&quot;))&quot;)<br>    }<br>}<br><br>// Builder Interface<br>protocol UserProfileBuilder {<br>    func setUsername(_ username: String) -&gt; UserProfileBuilder<br>    func setBiography(_ biography: String) -&gt; UserProfileBuilder<br>    func setLocation(_ location: String) -&gt; UserProfileBuilder<br>    func setInterests(_ interests: [String]) -&gt; UserProfileBuilder<br>    func setProfilePictureURL(_ url: String) -&gt; UserProfileBuilder<br>    func build() -&gt; UserProfile<br>}<br><br>// Concrete Builder<br>class UserProfileConcreteBuilder: UserProfileBuilder {<br>    private var userProfile = UserProfile(username: &quot;&quot;)<br>    <br>    func reset() {<br>        userProfile = UserProfile(username: userProfile.username)<br>    }<br>    <br>    func setUsername(_ username: String) -&gt; UserProfileBuilder {<br>        userProfile.username = username<br>        return self<br>    }<br>    <br>    func setBiography(_ biography: String) -&gt; UserProfileBuilder {<br>        userProfile.biography = biography<br>        return self<br>    }<br>    <br>    func setLocation(_ location: String) -&gt; UserProfileBuilder {<br>        userProfile.location = location<br>        return self<br>    }<br>    <br>    func setInterests(_ interests: [String]) -&gt; UserProfileBuilder {<br>        userProfile.interests = interests<br>        return self<br>    }<br>    <br>    func setProfilePictureURL(_ url: String) -&gt; UserProfileBuilder {<br>        userProfile.profilePictureURL = url<br>        return self<br>    }<br>    <br>    func build() -&gt; UserProfile {<br>        return userProfile<br>    }<br>}<br><br>// Usage<br>let builder = UserProfileConcreteBuilder()<br>let userProfile = builder.setUsername(&quot;john_doe&quot;)<br>                            .setBiography(&quot;Love to travel and code.&quot;)<br>                            .setLocation(&quot;New York, USA&quot;)<br>                            .setInterests([&quot;Coding&quot;, &quot;Traveling&quot;, &quot;Photography&quot;])<br>                            .setProfilePictureURL(&quot;http://example.com/profile.jpg&quot;)<br>                            .build()<br><br>userProfile.describe()</pre><ul><li>This example shows how the Builder pattern facilitates the creation of complex objects (like a user profile) step-by-step.</li><li>The UserProfileConcreteBuilder allows optional properties to be set flexibly, making it easy to create a UserProfile with just the required details or with a fully detailed profile.</li><li>This approach enhances code readability and maintainability, especially when creating objects with numerous attributes or when some attributes are optional.</li></ul><h3>Other usages</h3><p>Many open sources or frameworks widely use this pattern, especially those involving complex object creation, configuration management, and user interface construction.</p><p>Here are a few notable examples:</p><h4>1. SwiftUI</h4><pre>Text(&quot;Hello, World!&quot;)<br>    .font(.title)<br>    .padding()<br>    .background(Color.yellow)<br>    .cornerRadius(10)</pre><p>Although not a direct implementation of the Builder pattern in the traditional sense, SwiftUI’s way of constructing views with modifiers resembles the Builder pattern’s step-by-step construction and method chaining.</p><h4>2. Spring Boot (Java)</h4><pre>new SpringApplicationBuilder()<br>   .sources(Application.class)<br>   .bannerMode(Banner.Mode.OFF)<br>   .run(args);</pre><p>Spring Boot, a popular open-source Java-based framework, uses the Builder pattern to configure and bootstrap the application in a fluent API style.</p><p>For instance, the SpringApplicationBuilder class allows for the fluent configuration of a Spring application.</p><h4>3. .NET Core &amp; Entity Framework Core</h4><pre><br>protected override void OnModelCreating(ModelBuilder modelBuilder)<br>{<br>   modelBuilder.Entity&lt;Student&gt;()<br>   .Property(s =&gt; s.Name)<br>   .IsRequired();<br>}</pre><p>Entity Framework Core uses the Builder pattern extensively for model configuration in its Fluent API. Developers define the model configuration in the OnModelCreating method using the ModelBuilder class.</p><ul><li><a href="https://refactoring.guru/design-patterns/builder">Builder</a></li><li><a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern - Wikipedia</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4aed8093887b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Real World Design Pattern for iOS [2] — Memento]]></title>
            <link>https://enebin.medium.com/real-world-design-pattern-for-ios-2-memento-15ca013ffdbe?source=rss-84589cdcce2f------2</link>
            <guid isPermaLink="false">https://medium.com/p/15ca013ffdbe</guid>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[enebin]]></dc:creator>
            <pubDate>Fri, 22 Mar 2024 22:43:14 GMT</pubDate>
            <atom:updated>2024-03-24T01:56:11.111Z</atom:updated>
            <content:encoded><![CDATA[<h3>Real World Design Pattern for iOS [2] — Memento</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zZHTMKWAQrWVWzoR" /><figcaption>Photo by <a href="https://unsplash.com/@dialex?utm_source=medium&amp;utm_medium=referral">Diogo Nunes</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>What is Memento pattern?</h3><p>The Memento pattern is a design pattern that <strong>allows an object to save its state to a memento and restore it to a previous state</strong> from a memento without revealing its implementation details.</p><p>It involves three key components</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/0*NuzQzLf1aJlrHW4m.png" /><figcaption>Image from <a href="https://refactoring.guru/design-patterns/memento">Memento (refactoring.guru)</a></figcaption></figure><h4>1. Originator</h4><p>The object whose state needs to be saved and can be restored to a previous state.</p><h4>2. Memento</h4><p>An object that stores the state of the originator. It has two interfaces; Caretaker sees a narrow interface that allows it to store and retrieve the memento, while Originator sees a wide interface that allows it to access all the data necessary to restore the previous state.</p><h4>3. Caretaker</h4><p>An object that keeps the memento. The caretaker requests a save from the originator to capture the current state and uses the memento to bring the originator back to a previous state. However, it does not modify the memento itself.</p><h3>Why should we use it?</h3><p><strong>It helps in keeping the history of an object’s state without exposing its internal structure</strong>, thus following the encapsulation principle.</p><p>This pattern is especially useful for implementing undo mechanisms or for saving and restoring the state of an object at a given point in time.</p><h3>Real world example</h3><h4>1. Text Editor Undo Feature</h4><ul><li><strong>Originator</strong>: TextEditor</li><li><strong>Memento</strong>: EditorState</li><li><strong>Caretaker</strong>: History</li></ul><pre><br>// Originator<br>class TextEditor {<br>    private var content: String = &quot;&quot;<br>    <br>    func type(_ text: String) {<br>        content += text<br>    }<br>    <br>    func save() -&gt; EditorState {<br>        return EditorState(content: content)<br>    }<br>    <br>    func restore(state: EditorState) {<br>        content = state.getContent()<br>    }<br>    <br>    func getContent() -&gt; String {<br>        return content<br>    }<br>}<br><br>// Memento<br>class EditorState {<br>    private let content: String<br>    <br>    init(content: String) {<br>        self.content = content<br>    }<br>    <br>    func getContent() -&gt; String {<br>        return content<br>    }<br>}<br><br>// Caretaker<br>class History {<br>    private var states = [EditorState]()<br>    <br>    func save(state: EditorState) {<br>        states.append(state)<br>    }<br>    <br>    func undo() -&gt; EditorState? {<br>        return states.popLast()<br>    }<br>}<br><br>// Usage<br>let editor = TextEditor()<br>let history = History()<br>editor.type(&quot;First Sentence. &quot;)<br>history.save(state: editor.save())<br>editor.type(&quot;Second Sentence. &quot;)<br>history.save(state: editor.save())<br><br>// User decides to undo the last action<br>if let prevState = history.undo() {<br>    editor.restore(state: prevState)<br>}<br>print(editor.getContent())<br>// Output: First Sentence.</pre><ul><li>This example demonstrates the Memento pattern applied in a text editor for an undo feature, where the TextEditor acts as the Originator, capable of saving its state (EditorState) and restoring it later.</li><li>This setup allows the application to revert the text editor’s content to a previous state, encapsulating the complexities of state management and ensuring the editor’s internal structure is not exposed.</li></ul><h4>2. Game State Save and Load System</h4><ul><li>Originator: GameLevel</li><li>Memento: GameState</li><li>Caretaker: SaveLoadManager</li></ul><pre><br>// Originator<br>class GameLevel {<br>    private var level: Int<br>    private var checkpoints: Int<br>    <br>    init(level: Int, checkpoints: Int) {<br>        self.level = level<br>        self.checkpoints = checkpoints<br>    }<br>    <br>    func play(newLevel: Int, newCheckpoints: Int) {<br>        level = newLevel<br>        checkpoints = newCheckpoints<br>    }<br>    <br>    func save() -&gt; GameState {<br>        return GameState(level: level, checkpoints: checkpoints)<br>    }<br>    <br>    func restore(state: GameState) {<br>        level = state.getLevel()<br>        checkpoints = state.getCheckpoints()<br>    }<br>    <br>    func displayStatus() {<br>        print(&quot;Level: \(level), Checkpoints: \(checkpoints)&quot;)<br>    }<br>}<br><br>// Memento<br>class GameState {<br>    private var level: Int<br>    private var checkpoints: Int<br>    <br>    init(level: Int, checkpoints: Int) {<br>        self.level = level<br>        self.checkpoints = checkpoints<br>    }<br>    <br>    func getLevel() -&gt; Int {<br>        return level<br>    }<br>    <br>    func getCheckpoints() -&gt; Int {<br>        return checkpoints<br>    }<br>}<br><br>// Caretaker<br>class SaveLoadManager {<br>    private var saves = [GameState]()<br>    <br>    func save(state: GameState) {<br>        saves.append(state)<br>    }<br>    <br>    func load() -&gt; GameState? {<br>        return saves.last<br>    }<br>}<br><br>// Usage<br>let game = GameLevel(level: 1, checkpoints: 5)<br>let manager = SaveLoadManager()<br><br>// Playing game…<br>game.play(newLevel: 2, newCheckpoints: 10)<br>manager.save(state: game.save())<br>// Further progress…<br>game.play(newLevel: 3, newCheckpoints: 20)<br>// Need to revert to the previous state<br>if let savedGame = manager.load() {<br>    game.restore(state: savedGame)<br>}<br><br>game.displayStatus()<br>// Output: Level: 2, Checkpoints: 10</pre><ul><li>This example illustrates the Memento pattern in a gaming context, where the GameLevel acts as the Originator, capable of saving its current state (level and checkpoints) into a GameState (the Memento) and restoring from it.</li><li>This system enables a save and load functionality, allowing players to save their progress and return to a saved state later, encapsulating the state saving logic while maintaining game level encapsulation.</li></ul><ul><li><a href="https://en.wikipedia.org/wiki/Memento_pattern">Memento pattern - Wikipedia</a></li><li><a href="https://refactoring.guru/design-patterns/memento">Memento</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=15ca013ffdbe" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>