<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Arseni Kavalchuk</title>
    <description>The latest articles on DEV Community by Arseni Kavalchuk (@arsenikavalchuk).</description>
    <link>https://dev.to/arsenikavalchuk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1075012%2F313f2aa0-25d7-43fa-9082-e388a0c7d9b7.jpg</url>
      <title>DEV Community: Arseni Kavalchuk</title>
      <link>https://dev.to/arsenikavalchuk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arsenikavalchuk"/>
    <language>en</language>
    <item>
      <title>Coding Agents for Software Engineers</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Mon, 23 Feb 2026 01:02:36 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/coding-agents-for-software-engineers-73p</link>
      <guid>https://dev.to/arsenikavalchuk/coding-agents-for-software-engineers-73p</guid>
      <description>&lt;h3&gt;
  
  
  Architecture, Context, and Efficient Usage
&lt;/h3&gt;




&lt;h2&gt;
  
  
  1️⃣ What Is a Coding Agent?
&lt;/h2&gt;

&lt;p&gt;A coding agent is &lt;strong&gt;not just an LLM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is a system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IDE / CLI
    ↓
Agent Runtime
    ↓
Context Builder
    ↓
LLM Inference
    ↓
Tool Execution (fs, git, tests, shell)
    ↓
Loop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model is only the reasoning engine.&lt;br&gt;
The runtime handles orchestration.&lt;/p&gt;


&lt;h2&gt;
  
  
  2️⃣ General Architecture of a Coding Agent
&lt;/h2&gt;

&lt;p&gt;A production-grade coding agent includes:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Indexing Layer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Repo scanning&lt;/li&gt;
&lt;li&gt;Symbol extraction&lt;/li&gt;
&lt;li&gt;Dependency graph&lt;/li&gt;
&lt;li&gt;Optional embeddings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Context Builder
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Select relevant files&lt;/li&gt;
&lt;li&gt;Inject instructions&lt;/li&gt;
&lt;li&gt;Add plan/scratchpad&lt;/li&gt;
&lt;li&gt;Add recent edits&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  3. LLM Inference Layer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tokenized prompt&lt;/li&gt;
&lt;li&gt;Context window constraints&lt;/li&gt;
&lt;li&gt;Streaming output&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  4. Tool Layer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;File read/write&lt;/li&gt;
&lt;li&gt;Test execution&lt;/li&gt;
&lt;li&gt;Git diff/patch&lt;/li&gt;
&lt;li&gt;Lint/build commands&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  5. Loop Controller
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Plan&lt;/li&gt;
&lt;li&gt;Execute&lt;/li&gt;
&lt;li&gt;Validate&lt;/li&gt;
&lt;li&gt;Iterate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model does not “see the repo.”&lt;br&gt;
The agent chooses what to send.&lt;/p&gt;


&lt;h2&gt;
  
  
  3️⃣ What Is the Context Window?
&lt;/h2&gt;

&lt;p&gt;The context window is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The maximum number of tokens the model can attend to in a single inference call.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System instructions
+ AGENTS.md / policies
+ Scratchpad / plan files
+ Relevant source files
+ Recent conversation
+ Tool outputs
+ Your current request
+ Model output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything must fit inside the window.&lt;/p&gt;

&lt;p&gt;Large window ≠ send everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  4️⃣ Where Does Tokenization Happen?
&lt;/h2&gt;

&lt;p&gt;Typically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The agent runtime tokenizes locally (client-side).&lt;/li&gt;
&lt;li&gt;It estimates token usage before calling the model.&lt;/li&gt;
&lt;li&gt;The server still processes tokens during inference.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why client-side tokenization matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid exceeding context&lt;/li&gt;
&lt;li&gt;Control cost&lt;/li&gt;
&lt;li&gt;Control chunking&lt;/li&gt;
&lt;li&gt;Optimize file selection&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5️⃣ What Actually Consumes Tokens?
&lt;/h2&gt;

&lt;p&gt;In coding workflows, token cost usually comes from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large source files&lt;/li&gt;
&lt;li&gt;Test files&lt;/li&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;li&gt;Replayed conversation history&lt;/li&gt;
&lt;li&gt;Repeated system instructions&lt;/li&gt;
&lt;li&gt;Scratchpad growth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your instruction verbosity is rarely the main cost.&lt;br&gt;
File selection is.&lt;/p&gt;


&lt;h2&gt;
  
  
  6️⃣ What Makes “Good Quality” Context?
&lt;/h2&gt;

&lt;p&gt;Good context is:&lt;/p&gt;
&lt;h3&gt;
  
  
  ✅ Relevant
&lt;/h3&gt;

&lt;p&gt;Only include files that matter.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✅ Structured
&lt;/h3&gt;

&lt;p&gt;Clear task → constraints → deliverable.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✅ Deterministic
&lt;/h3&gt;

&lt;p&gt;Explicit scope boundaries.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✅ Minimal but sufficient
&lt;/h3&gt;

&lt;p&gt;No narrative fluff.&lt;br&gt;
No repeated architecture explanation.&lt;/p&gt;

&lt;p&gt;Bad context is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entire repo dump&lt;/li&gt;
&lt;li&gt;Long emotional explanations&lt;/li&gt;
&lt;li&gt;Old irrelevant chat history&lt;/li&gt;
&lt;li&gt;Ambiguous instructions&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  7️⃣ What Actually Improves Coding Responses?
&lt;/h2&gt;

&lt;p&gt;Not politeness.&lt;br&gt;
Not verbosity.&lt;/p&gt;

&lt;p&gt;What improves results:&lt;/p&gt;
&lt;h3&gt;
  
  
  1️⃣ Clear Scope
&lt;/h3&gt;

&lt;p&gt;Bad:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Improve authentication system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scope:
- src/auth/*
- src/middleware/auth.ts
Do not touch:
- public API
- schema definitions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2️⃣ Explicit Constraints
&lt;/h3&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not change public interfaces.&lt;/li&gt;
&lt;li&gt;Preserve test behavior.&lt;/li&gt;
&lt;li&gt;No new dependencies.&lt;/li&gt;
&lt;li&gt;Keep diff minimal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Constraints reduce hallucinated refactors.&lt;/p&gt;




&lt;h3&gt;
  
  
  3️⃣ Defined Output Format
&lt;/h3&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deliverable:
- Unified diff only
- Brief explanation (&amp;lt;150 words)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reduces drift.&lt;/p&gt;




&lt;h3&gt;
  
  
  4️⃣ Plan-First Workflow
&lt;/h3&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implement feature X.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1: Generate PLAN.md
Step 2: Review plan
Step 3: Implement Step 1 only
Step 4: Run tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Planning reduces chaotic edits.&lt;/p&gt;




&lt;h2&gt;
  
  
  8️⃣ Scratchpads and Plan Files
&lt;/h2&gt;

&lt;p&gt;Scratchpad = external reasoning state.&lt;/p&gt;

&lt;p&gt;Can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PLAN.md&lt;/li&gt;
&lt;li&gt;TODO.md&lt;/li&gt;
&lt;li&gt;In-memory state&lt;/li&gt;
&lt;li&gt;Conversation buffer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-step tracking&lt;/li&gt;
&lt;li&gt;Reduced re-reasoning&lt;/li&gt;
&lt;li&gt;Human-agent alignment&lt;/li&gt;
&lt;li&gt;Safer iteration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But:&lt;br&gt;
The model does not remember it.&lt;br&gt;
The agent injects it into context each time.&lt;/p&gt;


&lt;h2&gt;
  
  
  9️⃣ Efficient Project Structure for Coding Agents
&lt;/h2&gt;

&lt;p&gt;Recommended:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/AGENTS.md        # Global behavior rules (minimal)
/PLAN.md          # Task plan (editable)
/src/...
/tests/...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  AGENTS.md should contain:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Coding standards&lt;/li&gt;
&lt;li&gt;Test commands&lt;/li&gt;
&lt;li&gt;“Plan first” rule&lt;/li&gt;
&lt;li&gt;Guardrails&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep it short.&lt;br&gt;
It is injected often.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔟 Efficient Coding Agent Usage Patterns
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Pattern A — Constrained Patch
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Task:
Optimize middleware performance.

Scope:
src/auth/middleware.ts

Constraints:
- Preserve API
- No new deps

Output:
Unified diff only.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern B — Incremental Execution
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Implement only Step 1 from PLAN.md.
Run tests.
Update PLAN.md.
Stop.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern C — Scope Locking
&lt;/h3&gt;

&lt;p&gt;Explicitly limit directories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Touch only:
src/auth/*
Do not modify:
src/db/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents token waste and unintended edits.&lt;/p&gt;




&lt;h2&gt;
  
  
  1️⃣1️⃣ What NOT to Do
&lt;/h2&gt;

&lt;p&gt;❌ Send the whole repo&lt;br&gt;
❌ Re-explain system architecture every turn&lt;br&gt;
❌ Let scratchpads grow unbounded&lt;br&gt;
❌ Leave scope ambiguous&lt;br&gt;
❌ Ask for “improve everything”&lt;/p&gt;


&lt;h2&gt;
  
  
  1️⃣2️⃣ Big Context Myth
&lt;/h2&gt;

&lt;p&gt;A 1M token context window does not mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You should send 1M tokens.&lt;/li&gt;
&lt;li&gt;It will be faster.&lt;/li&gt;
&lt;li&gt;It will be more accurate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Longer context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increases latency&lt;/li&gt;
&lt;li&gt;Increases cost&lt;/li&gt;
&lt;li&gt;Increases noise risk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Smart context selection beats large context.&lt;/p&gt;


&lt;h2&gt;
  
  
  1️⃣3️⃣ Mental Model for Engineers
&lt;/h2&gt;

&lt;p&gt;Treat coding agents like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LLM = Stateless reasoning engine
Context = Input data packet
Agent = Orchestrator
Scratchpad = External memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your job:&lt;br&gt;
Optimize the data packet.&lt;/p&gt;




&lt;h2&gt;
  
  
  1️⃣4️⃣ Core Optimization Principles
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Structure &amp;gt; verbosity&lt;/li&gt;
&lt;li&gt;Relevance &amp;gt; completeness&lt;/li&gt;
&lt;li&gt;Constraints &amp;gt; freedom&lt;/li&gt;
&lt;li&gt;Iteration &amp;gt; giant prompts&lt;/li&gt;
&lt;li&gt;Plan → execute → verify&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;Coding agents perform best when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The task is clearly scoped&lt;/li&gt;
&lt;li&gt;Constraints are explicit&lt;/li&gt;
&lt;li&gt;Context is curated&lt;/li&gt;
&lt;li&gt;Plans are externalized&lt;/li&gt;
&lt;li&gt;History is pruned&lt;/li&gt;
&lt;li&gt;Output format is constrained&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>codequality</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Effective Ways to Use Locks in Kotlin</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Sat, 14 Dec 2024 00:38:10 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/effective-ways-to-use-locks-in-kotlin-3j9b</link>
      <guid>https://dev.to/arsenikavalchuk/effective-ways-to-use-locks-in-kotlin-3j9b</guid>
      <description>&lt;p&gt;In Kotlin, locks play a critical role in ensuring thread safety when multiple threads access shared resources. Here are the common idiomatic ways to use locks in Kotlin:&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Using &lt;code&gt;ReentrantLock&lt;/code&gt; with &lt;code&gt;lock()&lt;/code&gt; and &lt;code&gt;unlock()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The most explicit way to use a lock in Kotlin is by calling &lt;code&gt;lock()&lt;/code&gt; and &lt;code&gt;unlock()&lt;/code&gt; manually. This provides fine-grained control over when the lock is acquired and released.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.locks.ReentrantLock&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SafeCounter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReentrantLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Explicitly acquire the lock&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;++&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Incremented to: $count"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Ensure the lock is released even if an exception occurs&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getCount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;counter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SafeCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;threads&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Final count: ${counter.getCount()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Using &lt;code&gt;withLock&lt;/code&gt; Extension Function
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;withLock&lt;/code&gt; extension function simplifies lock usage in Kotlin by managing the &lt;code&gt;lock()&lt;/code&gt; and &lt;code&gt;unlock()&lt;/code&gt; calls automatically.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.locks.ReentrantLock&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.concurrent.withLock&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SafeList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReentrantLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withLock&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withLock&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Return a copy for safety&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;safeList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SafeList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;threads&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;safeList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Item-$index"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Final list: ${safeList.getList()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Using &lt;code&gt;synchronized&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;synchronized&lt;/code&gt; keyword offers a simpler alternative for basic synchronization by locking on a specific monitor object.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SafeCounter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;synchronized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Synchronize on the instance itself&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;++&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Incremented to: $count"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getCount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;synchronized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;counter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SafeCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;threads&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Final count: ${counter.getCount()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Using &lt;code&gt;ReadWriteLock&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;For scenarios with frequent reads and infrequent writes, &lt;code&gt;ReadWriteLock&lt;/code&gt; provides separate locks for reading and writing, allowing multiple threads to read concurrently.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.locks.ReentrantReadWriteLock&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SafeMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReentrantReadWriteLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;map&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableMapOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeLock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeLock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readLock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readLock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;safeMap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SafeMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;threads&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;safeMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Key-$index"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Value-$index"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Final map: $safeMap"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. Using Coroutines and &lt;code&gt;Mutex&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;For coroutine-based concurrency, Kotlin offers the &lt;code&gt;Mutex&lt;/code&gt; class from &lt;code&gt;kotlinx.coroutines.sync&lt;/code&gt;. This is a coroutine-friendly lock that avoids blocking threads.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.sync.Mutex&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.sync.withLock&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SafeCounter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mutex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withLock&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;++&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Incremented to: $count"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getCount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runBlocking&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;counter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SafeCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;jobs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Final count: ${counter.getCount()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  6. Using Atomic Variables
&lt;/h3&gt;

&lt;p&gt;For simple scenarios, atomic variables like &lt;code&gt;AtomicInteger&lt;/code&gt; and &lt;code&gt;AtomicLong&lt;/code&gt; provide a lock-free alternative for thread-safe counters and accumulators.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.atomic.AtomicInteger&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SafeCounter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AtomicInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Incremented to: ${count.incrementAndGet()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getCount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;counter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SafeCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;threads&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Final count: ${counter.getCount()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  When to Use Each?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ReentrantLock&lt;/code&gt; + &lt;code&gt;lock/unlock&lt;/code&gt;&lt;/strong&gt;: Use for low-level control, especially when advanced features like interruptible locks are required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;withLock&lt;/code&gt;&lt;/strong&gt;: The idiomatic Kotlin approach for most use cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;synchronized&lt;/code&gt;&lt;/strong&gt;: Simple and straightforward for basic synchronization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ReadWriteLock&lt;/code&gt;&lt;/strong&gt;: Ideal for frequent reads and infrequent writes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Mutex&lt;/code&gt;&lt;/strong&gt;: Best for coroutine-based concurrency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atomic Variables&lt;/strong&gt;: Lightweight and lock-free, perfect for counters and accumulators.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each approach caters to specific needs based on complexity, performance, and whether you’re working with threads or coroutines. Understanding these options ensures you can write safe and efficient concurrent Kotlin applications.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>multithreading</category>
    </item>
    <item>
      <title>iOS String to Kotlin ByteArray Performance Analysis</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Mon, 18 Nov 2024 01:13:53 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/ios-string-to-kotlin-bytearray-performance-analysis-4edi</link>
      <guid>https://dev.to/arsenikavalchuk/ios-string-to-kotlin-bytearray-performance-analysis-4edi</guid>
      <description>&lt;p&gt;When working with Kotlin Multiplatform (KMP), interoperability between Kotlin and native code can introduce performance bottlenecks. One such case is converting a Swift &lt;code&gt;String&lt;/code&gt; into a Kotlin &lt;code&gt;ByteArray&lt;/code&gt;. In this article, we analyze the performance of several approaches to improve this conversion process. We write Swift &lt;code&gt;String&lt;/code&gt; extension functions and Kotlin &lt;code&gt;ByteArray&lt;/code&gt; factory methods using native pointers and system functions like &lt;code&gt;memcpy&lt;/code&gt; to optimize performance. &lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/ios-kmp/ios-kmpPerfTests/ios_kmpPerfTests.swift" rel="noopener noreferrer"&gt;Full source code&lt;/a&gt;. Refer to &lt;a href="https://dev.to/arsenikavalchuk/enhance-ios-development-with-kotlin-multiplatform-library-1h02"&gt;How to set up KMP library in iOS&lt;/a&gt; for the details about KMP library and integration with iOS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin ByteArray API in iOS
&lt;/h2&gt;

&lt;p&gt;The Kotlin &lt;code&gt;ByteArray&lt;/code&gt; is exposed to iOS as the &lt;code&gt;KotlinByteArray&lt;/code&gt; class, which provides basic methods like &lt;code&gt;get(index)&lt;/code&gt; and &lt;code&gt;set(index:value:)&lt;/code&gt;, and constructors like &lt;code&gt;init(size:)&lt;/code&gt;. However, this API is inefficient for scenarios requiring high-performance operations on byte arrays.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;KotlinByteArray&lt;/code&gt; Interface
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;objc_subclassing_restricted&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;swift_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"KotlinByteArray"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt; &lt;span class="n"&gt;KmpLibKotlinByteArray&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;KmpLibBase&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instancetype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;arrayWithSize&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="nf"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;swift_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"init(size:)"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int8_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;getIndex&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="nf"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;swift_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"get(index:)"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;setIndex&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int8_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="nf"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;swift_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"set(index:value:)"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readonly&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="nf"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;swift_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interface makes random access and element-wise operations slow due to its lack of batch processing capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Native APIs in KMP
&lt;/h2&gt;

&lt;p&gt;KMP common code cannot access native APIs directly, but native parts of the KMP code can leverage platform-specific functions plus using &lt;code&gt;cinterop&lt;/code&gt; API. This enables us to optimize byte array copying by using native constructs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Working with Native Pointers
&lt;/h3&gt;

&lt;p&gt;In Kotlin/Native, the &lt;code&gt;CPointer&lt;/code&gt; type is used to interface with raw memory through pointers. Understanding the differences between pointer types like &lt;code&gt;CPointer&amp;lt;Byte&amp;gt;&lt;/code&gt; and &lt;code&gt;CPointer&amp;lt;ByteVar&amp;gt;&lt;/code&gt; is essential for efficient memory operations and interoperability with native libraries.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CPointer&amp;lt;Byte&amp;gt;&lt;/code&gt; represents a pointer to an immutable sequence of bytes. It is typically used when you want to read data from a memory location without modifying its content. This type is ideal for operations where the memory is treated as read-only, such as parsing a buffer or reading data from a constant memory region.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;printByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CPointer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Byte&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;data&lt;/code&gt; points to a sequence of bytes, and the function iterates over the memory to print each byte.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CPointer&amp;lt;ByteVar&amp;gt;&lt;/code&gt; is a pointer to a mutable byte variable. It is used for memory regions that can be written to, such as buffers for receiving data or memory blocks that are initialized and modified. The &lt;code&gt;ByteVar&lt;/code&gt; type encapsulates a mutable &lt;code&gt;Byte&lt;/code&gt; value in Kotlin/Native, allowing operations like setting new values or performing in-place modifications.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;setByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CPointer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ByteVar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;data&lt;/code&gt; is a mutable pointer, and the function writes a specified &lt;code&gt;value&lt;/code&gt; to each byte in the memory block.&lt;/p&gt;

&lt;h3&gt;
  
  
  Default ByteArray Handling
&lt;/h3&gt;

&lt;p&gt;The Kotlin/Native &lt;code&gt;ByteArray.readBytes&lt;/code&gt; is a convenient but inefficient function that loops over each byte, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@OptIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExperimentalForeignApi&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;byteArrayFromPtrReadBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CPointer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ByteVar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ByteArray&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This essentially goes into this &lt;a href="https://github.com/JetBrains/kotlin/blob/5517b3a8c9559f589b4f1e8593291ed24ffdefad/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt#L50" rel="noopener noreferrer"&gt;implementation in Kotlin&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NativePointed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ByteArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;sourceArray&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reinterpret&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ByteVar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sourceArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optimizing with &lt;code&gt;memcpy&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of looping, we can use the highly efficient POSIX &lt;code&gt;memcpy&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@OptIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExperimentalForeignApi&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;byteArrayFromPtrMemcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CPointer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ByteVar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ByteArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;also&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;usePinned&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;pinned&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pinned&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addressOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toULong&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing Approaches
&lt;/h2&gt;

&lt;p&gt;We implemented five test cases to compare performance:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Loop Copy&lt;/strong&gt;: Convert a Swift &lt;code&gt;String&lt;/code&gt; to a byte array using a loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ReadBytes&lt;/strong&gt;: Use &lt;code&gt;ByteArray.readBytes&lt;/code&gt; to copy from a pointer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memcpy&lt;/strong&gt;: Use &lt;code&gt;memcpy&lt;/code&gt; to copy from a pointer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swift UTF8 Byte Array&lt;/strong&gt;: Convert &lt;code&gt;String.utf8&lt;/code&gt; to a byte array and compare performance with &lt;code&gt;readBytes&lt;/code&gt; and &lt;code&gt;memcpy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swift UTF8 CString Pointer&lt;/strong&gt;: Use &lt;code&gt;String.utf8CString&lt;/code&gt; with both &lt;code&gt;readBytes&lt;/code&gt; and &lt;code&gt;memcpy&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Swift Implementations
&lt;/h3&gt;

&lt;p&gt;Here are the Swift extension functions:&lt;/p&gt;

&lt;h4&gt;
  
  
  Loop Copy
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;toKotlinByteArrayLoopCopy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;utf8Bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;kotlinByteArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utf8Bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;utf8Bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enumerated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;kotlinByteArray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;bitPattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;kotlinByteArray&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Data Pointer with &lt;code&gt;readBytes&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;toKotlinByteArrayDataPtrReadBytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withUnsafeMutableBytes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="kt"&gt;ByteArrayUtilKt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;byteArrayFromPtrReadBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baseAddress&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Data Pointer with &lt;code&gt;memcpy&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;toKotlinByteArrayDataPtrMemcpy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withUnsafeMutableBytes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="kt"&gt;ByteArrayUtilKt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;byteArrayFromPtrMemcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baseAddress&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  UTF8 CString with &lt;code&gt;readBytes&lt;/code&gt; and &lt;code&gt;memcpy&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;toKotlinByteArrayUtf8CStringReadBytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utf8CString&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withUnsafeMutableBufferPointer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="kt"&gt;ByteArrayUtilKt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;byteArrayFromPtrReadBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baseAddress&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baseAddress&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;toKotlinByteArrayUtf8CStringMemcpy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utf8CString&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withUnsafeMutableBufferPointer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="kt"&gt;ByteArrayUtilKt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;byteArrayFromPtrMemcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baseAddress&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baseAddress&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benchmark Results
&lt;/h2&gt;

&lt;p&gt;The results from running 1000 iterations of each method:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Time (ms)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LoopCopy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;32.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DataPtrReadBytes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Utf8CStringReadBytes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.89&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DataPtrMemcpy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Utf8CStringMemcpy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.02&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Insights
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LoopCopy&lt;/strong&gt; is the slowest, due to its repeated calls to &lt;code&gt;set(index:value:)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;readBytes&lt;/strong&gt; significantly improves performance but is still not optimal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memcpy&lt;/strong&gt; is the fastest method due to its highly efficient memory operations.&lt;/li&gt;
&lt;li&gt;The combination of Swift's &lt;code&gt;utf8CString&lt;/code&gt; and Kotlin's &lt;code&gt;memcpy&lt;/code&gt; achieves the best performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For optimal performance when converting a Swift &lt;code&gt;String&lt;/code&gt; to a Kotlin &lt;code&gt;ByteArray&lt;/code&gt;, use the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kotlin&lt;/strong&gt;: Implement a &lt;code&gt;ByteArray&lt;/code&gt; factory using &lt;code&gt;memcpy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swift&lt;/strong&gt;: Use &lt;code&gt;utf8CString&lt;/code&gt; with unsafe buffer pointers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This combination delivers minimal overhead, unlocking high-performance interoperability in KMP.&lt;/p&gt;

&lt;p&gt;The full implementation is in &lt;a href="https://github.com/arskov/ios-kmp-lib" rel="noopener noreferrer"&gt;the project on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Enhance iOS Development with Kotlin Multiplatform Library</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Sun, 17 Nov 2024 18:37:18 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/enhance-ios-development-with-kotlin-multiplatform-library-1h02</link>
      <guid>https://dev.to/arsenikavalchuk/enhance-ios-development-with-kotlin-multiplatform-library-1h02</guid>
      <description>&lt;p&gt;Kotlin Multiplatform (KMP) is a promising approach that enables developers to share business logic across multiple platforms, including iOS and Android, while allowing platform-specific implementations for platform-dependent functionalities. This article demonstrates how to integrate KMP with iOS, showcasing how to expose Kotlin interfaces to Swift, implement these interfaces in Swift, and leverage them in a Swift UI application.&lt;/p&gt;

&lt;p&gt;The focus here is to explore an alternative approach that avoids the complexity of &lt;code&gt;expect/actual&lt;/code&gt; patterns. Instead, this method streamlines the integration by minimizing the interaction with platform APIs not exposed in KMP.&lt;/p&gt;

&lt;p&gt;We’ll build a sample Swift UI application that encrypts, stores, and decrypts data. The business logic resides in Kotlin, while platform-specific functionality is implemented in Swift.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up the Kotlin Mutliplatform Library in Android Studio
&lt;/h2&gt;

&lt;p&gt;To begin, you’ll need to create a KMP library using Android Studio. For reference, you can use the &lt;a href="https://github.com/arskov/ios-kmp-lib/tree/main/kmp-lib" rel="noopener noreferrer"&gt;example project&lt;/a&gt;. The &lt;code&gt;build.gradle.kts&lt;/code&gt; file for the library includes important configurations for creating a multiplatform library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Steps:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use basic KMP project structure. See example project for the reference&lt;/li&gt;
&lt;li&gt;Define a list of iOS targets &lt;code&gt;iosX64&lt;/code&gt;, &lt;code&gt;iosArm64&lt;/code&gt;, &lt;code&gt;iosSimulatorArm64&lt;/code&gt; in your &lt;code&gt;build.gradle.kts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Define &lt;code&gt;XCFramework&lt;/code&gt; with a variable and add all targets to the framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The key point here is that you need to give some meaningful name to your framework as well as using the same name for the framework binary&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The minimal &lt;code&gt;build.gradle.kts&lt;/code&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jetbrains.kotlin.gradle.dsl.JvmTarget&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework&lt;/span&gt;

&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kotlinMultiplatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;androidLibrary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"io.github.arskov"&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.0.0"&lt;/span&gt;

&lt;span class="c1"&gt;// Use some name for the framework. It will be used as main import in Swift&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;iosXCFrameworkName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"KmpLib"&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;binaryName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"kmp-lib"&lt;/span&gt;

&lt;span class="nf"&gt;kotlin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nf"&gt;androidTarget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;publishLibraryVariants&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nd"&gt;@OptIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExperimentalKotlinGradlePluginApi&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;compilerOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;jvmTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JvmTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;JVM_1_8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;xcf&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;XCFramework&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iosXCFrameworkName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;iosTargets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;iosX64&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;iosArm64&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;iosSimulatorArm64&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;iosTargets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;binaries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;framework&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;baseName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;iosXCFrameworkName&lt;/span&gt;
            &lt;span class="n"&gt;xcf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;sourceSets&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;commonMain&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Put necessary KMP compatible dependencies here&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;commonTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;android&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"io.github.arskov"&lt;/span&gt;
    &lt;span class="n"&gt;compileSdk&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compileSdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;defaultConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;minSdk&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minSdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the Gradle task to build the library, producing an XCFramework for iOS integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Architecture and Business Logic
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kotlin module contains &lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/kmp-lib/library/src/commonMain/kotlin/MultiplatformService.kt" rel="noopener noreferrer"&gt;MultiplatformService&lt;/a&gt; which accepts 2 interfaces as dependencies: &lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/kmp-lib/library/src/commonMain/kotlin/CryptoProvider.kt" rel="noopener noreferrer"&gt;CryptoProvider&lt;/a&gt; and &lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/kmp-lib/library/src/commonMain/kotlin/StoreProvider.kt" rel="noopener noreferrer"&gt;StoreProvider&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.github.arskov&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MultiplatformService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;cryptoProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CryptoProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;storeProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;StoreProvider&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Throws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StoreException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EncryptionException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;storeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PlainData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encryptionKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ByteArray&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;encryptionKey&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;encryptedData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                &lt;span class="n"&gt;cryptoProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EncryptOp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ENCRYPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encryptionKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;encryptedPlainData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                &lt;span class="nc"&gt;PlainData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encryptedData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;storeProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryptedPlainData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;storeProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Throws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StoreException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EncryptionException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;loadData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encryptionKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ByteArray&lt;/span&gt;&lt;span class="p"&gt;?):&lt;/span&gt; &lt;span class="nc"&gt;PlainData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storeProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;encryptionKey&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;decryptedData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cryptoProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EncryptOp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DECRYPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encryptionKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PlainData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decryptedData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main idea of the library is accepting the data, perform a provided crypto operation, and store the value in the provided store.&lt;/p&gt;

&lt;p&gt;For simplicity, we also have a default in-memory implementation of the &lt;code&gt;StoreProvider&lt;/code&gt;, but this could also be implemented on the Swift side. See below.&lt;/p&gt;

&lt;p&gt;Now what we want to do is to integrate this &lt;code&gt;MultiplatformService&lt;/code&gt; into Swift UI sample application. In Swift when we construct the &lt;code&gt;MultiplatformService&lt;/code&gt; we provide a Swift implementation of the &lt;code&gt;CryptoProvider&lt;/code&gt; and the &lt;code&gt;StoreProvider&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building the XCFramework
&lt;/h2&gt;

&lt;p&gt;An XCFramework is a container that supports multiple architectures, allowing your library to work seamlessly on different iOS devices and simulators.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps to Build the XCFramework:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set the Framework Name&lt;/strong&gt;: Ensure the framework has a clear and unique name, like &lt;code&gt;KmpLib&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specify Target Platforms&lt;/strong&gt;: Define architectures such as &lt;code&gt;iosArm64&lt;/code&gt; for physical devices and &lt;code&gt;iosSimulatorArm64&lt;/code&gt; for simulators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the Build Task&lt;/strong&gt;: 
Use &lt;code&gt;./gradlew task&lt;/code&gt; to see what are the possible assemble tasks you have.
Use the Gradle task &lt;code&gt;./gradlew assembleKmpLibXCFramework&lt;/code&gt; to build the XCFramework. The output will be located in the &lt;code&gt;kmp-lib/library/build/XCFrameworks/{debug|release}/&lt;/code&gt; directory. Gradle generates assembleXCFramework task if you give your framework a name.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Sample Swift UI Application
&lt;/h2&gt;

&lt;p&gt;The Swift UI application demonstrates how to utilize the KMP library for secure data management. Here's a high-level overview of its functionality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encryption&lt;/strong&gt;: Data is encrypted using the &lt;code&gt;CryptoProvider&lt;/code&gt; interface implemented in Swift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage&lt;/strong&gt;: Encrypted data is stored using the &lt;code&gt;InMemoryStoreProvider&lt;/code&gt; or a custom implementation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decryption&lt;/strong&gt;: The app retrieves and decrypts the data for display.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Workflow:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Input sample data into the app.&lt;/li&gt;
&lt;li&gt;Encrypt and store the data using Kotlin’s business logic.&lt;/li&gt;
&lt;li&gt;Retrieve and decrypt the data, showcasing the seamless interplay between Swift and KMP.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07d6lfsillfukx12aqb8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07d6lfsillfukx12aqb8.png" alt="Application in Xcode" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app architecture is minimalist yet demonstrates how Kotlin Multiplatform libraries can enhance iOS development.&lt;/p&gt;




&lt;h2&gt;
  
  
  Importing the XCFramework into Xcode
&lt;/h2&gt;

&lt;p&gt;To use the generated XCFramework in your Xcode project, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new iOS Swift UI project using the Xcode wizard. You don't need any special steps for this, just follow the Xcode instructions.&lt;/li&gt;
&lt;li&gt;Click on a project to open a &lt;strong&gt;Project Settings&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Frameworks, Libraries, and Embedded Content&lt;/strong&gt;, click the &lt;strong&gt;+&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;Add the path to the XCFramework:
&lt;code&gt;kmp-lib/library/build/XCFrameworks/debug/KmpLib.xcframework&lt;/code&gt;. The framework will appear in the Frameworks section of the Project structure in the left tree panel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5seekwc5thczkew4yt8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5seekwc5thczkew4yt8m.png" alt="Xcode settings" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This integration allows Swift to access Kotlin’s business logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementing KMP Interfaces in Swift
&lt;/h2&gt;

&lt;p&gt;In our example, we’ve imported the &lt;code&gt;KmpLib&lt;/code&gt; framework and now we are going to implement its exposed interfaces in Swift. The key interfaces are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/kmp-lib/library/src/commonMain/kotlin/CryptoProvider.kt" rel="noopener noreferrer"&gt;&lt;code&gt;CryptoProvider&lt;/code&gt;&lt;/a&gt;: Handles encryption and decryption of data.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/kmp-lib/library/src/commonMain/kotlin/StoreProvider.kt" rel="noopener noreferrer"&gt;&lt;code&gt;StoreProvider&lt;/code&gt;&lt;/a&gt;: Provides storage functionality. In this case, we use the default &lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/kmp-lib/library/src/commonMain/kotlin/InMemoryStoreProvider.kt" rel="noopener noreferrer"&gt;&lt;code&gt;InMemoryStoreProvider&lt;/code&gt;&lt;/a&gt; from KMP.&lt;/li&gt;
&lt;li&gt;Example of the &lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/ios-kmp/ios-kmp/IosCryptoProvider.swift" rel="noopener noreferrer"&gt;&lt;code&gt;IosCryptoProvider&lt;/code&gt;&lt;/a&gt; in Swift that implements the &lt;code&gt;CryptoProvider&lt;/code&gt; interface (a protocol in Swift)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;KmpLib&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;IosCryptoProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CryptoProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;op&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EncryptOp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Ensure the key is not empty&lt;/span&gt;
        &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;NSError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"CryptoError"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nv"&gt;userInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;NSLocalizedDescriptionKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Key must not be empty"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Create a result array of the same size as the data&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;KotlinByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// Perform XOR encryption&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;dataByte&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;keyByte&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dataByte&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;keyByte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ServiceLocator which contains the main code that instantiates and crates a Singleton for &lt;code&gt;MultiplatformService&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;
&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;KmpLib&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;ServiceLocator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;sharedInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ServiceLocator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;mutliplatformService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;MultiplatformService&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;storeProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;StoreProvider&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Swift implementation of the CryptoProvider protocol exposed from KMP&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;cryptoProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;IosCryptoProvider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;// KMP implementation of Stor&lt;/span&gt;
        &lt;span class="n"&gt;storeProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;InMemoryStoreProvider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;mutliplatformService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;MultiplatformService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nv"&gt;cryptoProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cryptoProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;storeProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;storeProvider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;getMultiplatformService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;MultiplatformService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutliplatformService&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;getStoreProvider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;StoreProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storeProvider&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/ios-kmp/ios-kmp/ContentView.swift" rel="noopener noreferrer"&gt;ContentView.swift&lt;/a&gt; file contains main UI logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the password for the content encryption&lt;/li&gt;
&lt;li&gt;Set the text&lt;/li&gt;
&lt;li&gt;Button to encrypt and store the content&lt;/li&gt;
&lt;li&gt;Controls to display the encrypted text in HEX&lt;/li&gt;
&lt;li&gt;Button to load and decrypt the content
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;            &lt;span class="kt"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ServiceLocator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharedInstance&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMultiplatformService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ServiceLocator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharedInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStoreProvider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;plainData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;PlainData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plainDataText&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toKotlinByteArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;storeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plainData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="nv"&gt;encryptionKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;encryptionKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toKotlinByteArray&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;storedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encryptedDataText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storedData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHexString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important detail, that we also crated some &lt;a href="https://github.com/arskov/ios-kmp-lib/blob/main/ios-kmp/ios-kmp/Conversion.swift" rel="noopener noreferrer"&gt;extension functions for &lt;code&gt;KotlinByteArray&lt;/code&gt; and &lt;code&gt;String&lt;/code&gt;&lt;/a&gt; to be able to easily convert between them. &lt;/p&gt;

&lt;p&gt;In production this copy operation is not cheap, and especially with the default methods that the KMP exposes for &lt;code&gt;KotlinByteArray&lt;/code&gt;, like &lt;code&gt;get(i)&lt;/code&gt;, &lt;code&gt;set(i, value)&lt;/code&gt;. We will consider alternatives in the follow up article &lt;a href="https://dev.to/arsenikavalchuk/ios-string-to-kotlin-bytearray-performance-analysis-4edi"&gt;iOS String to Kotlin ByteArray Performance Analysis &lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The running application looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2grx4j8533fo8unv1c2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2grx4j8533fo8unv1c2n.png" alt="Sample Application" width="800" height="1706"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article provided a step-by-step guide on leveraging Kotlin Multiplatform libraries for iOS development. By following this alternative approach, you can efficiently share business logic across platforms without delving into the complexities of &lt;code&gt;expect/actual&lt;/code&gt; APIs. The sample Swift UI application highlights the practical integration of KMP interfaces in Swift, showcasing the potential for streamlined cross-platform development.&lt;/p&gt;

&lt;p&gt;For further exploration, check out the complete example on &lt;a href="https://github.com/arskov/ios-kmp-lib" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>multiplatform</category>
      <category>ios</category>
      <category>swift</category>
    </item>
    <item>
      <title>Modern Dependency Injection with Koin: The Smart DI Choice for 2025</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Sat, 02 Nov 2024 15:48:44 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/modern-dependency-injection-with-koin-the-smart-di-choice-for-2025-550i</link>
      <guid>https://dev.to/arsenikavalchuk/modern-dependency-injection-with-koin-the-smart-di-choice-for-2025-550i</guid>
      <description>&lt;p&gt;In the Kotlin ecosystem, dependency injection (DI) frameworks are essential for managing dependencies, improving modularity, and streamlining application development. &lt;strong&gt;Koin&lt;/strong&gt; has emerged as a popular DI framework for Kotlin developers, especially valued for its simplicity, lightweight nature, and multiplatform support. At the time of writing, &lt;a href="https://github.com/InsertKoinIO/koin/releases/tag/4.0.0" rel="noopener noreferrer"&gt;Koin 4.0 has been released&lt;/a&gt;. Built on Kotlin 2.0, this release introduces a wide range of enhancements and Compose Multiplatform features. As we move into 2025, Koin continues to be an excellent choice, particularly because of its Kotlin-first design, ease of use, and adaptability across platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;strong&gt;Kotlin-First Design&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Koin was developed specifically with Kotlin in mind, making it a truly Kotlin-native DI framework. Unlike other DI frameworks adapted from Java, Koin’s syntax feels natural and intuitive for Kotlin developers. It leverages Kotlin’s expressive language features, resulting in cleaner and more concise code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Dependency Definition in Koin:
&lt;/h3&gt;

&lt;p&gt;In Koin, dependencies are defined within modules using a domain-specific language (DSL) in Kotlin. For instance, to define a repository and service dependency, you can use the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Defining dependencies in a Koin module&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;appModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;MyDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Defines a singleton of MyDatabase&lt;/span&gt;
    &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Defines a singleton of UserRepository that depends on MyDatabase&lt;/span&gt;
    &lt;span class="nf"&gt;factory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Defines a new instance of MyService whenever it’s injected&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;single&lt;/strong&gt;: Defines a singleton instance, meaning the same instance of &lt;code&gt;MyDatabase&lt;/code&gt; or &lt;code&gt;UserRepository&lt;/code&gt; is provided each time it’s needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;factory&lt;/strong&gt;: Creates a new instance each time &lt;code&gt;MyService&lt;/code&gt; is injected, useful for lightweight or short-lived components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This concise approach keeps dependency management straightforward, making Koin’s syntax highly readable and less error-prone.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;strong&gt;Easy to Learn and Integrate&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Koin’s simple and intuitive API makes it easy for developers to set up dependency injection without complex configurations. You can define your dependencies directly in Kotlin code without any XML files or annotations, making it easier to onboard new team members and start development quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Koin:
&lt;/h3&gt;

&lt;p&gt;To get started with Koin, all you need to do is &lt;a href="https://insert-koin.io/docs/setup/koin" rel="noopener noreferrer"&gt;define dependencies and the configuration&lt;/a&gt; in the Gradle project, define your modules and initialize Koin in the &lt;code&gt;Application&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Initializing Koin&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;// Starting Koin with the appModule&lt;/span&gt;
        &lt;span class="nf"&gt;startKoin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;androidContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MyApp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;startKoin&lt;/strong&gt;: Initializes Koin and loads the provided modules. Here, the &lt;code&gt;appModule&lt;/code&gt; defines all necessary dependencies for the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;androidContext&lt;/strong&gt;: Provides the Android context to Koin, allowing it to work seamlessly with Android components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup makes it easy to configure and manage dependencies, saving development time and reducing setup complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;strong&gt;Annotation-Free Dependency Injection&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While &lt;a href="https://insert-koin.io/docs/setup/annotations" rel="noopener noreferrer"&gt;annotations&lt;/a&gt; are supported, one of Koin's standout features is its annotation-free DI configuration, which aligns with the trend toward increased compile-time safety and code clarity. By using Kotlin code rather than annotations to declare dependencies, Koin makes it easier for developers to understand each component's dependencies at a glance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining Dependencies Without Annotations:
&lt;/h3&gt;

&lt;p&gt;Koin uses simple Kotlin functions and classes to define dependencies, avoiding the use of annotations altogether. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Define a ViewModel dependency&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;viewModelModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;viewModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;MyViewModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Dependency definition without annotations&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyViewModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;loadUserData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Business logic to load user data&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;viewModel&lt;/strong&gt;: A special Koin function for defining ViewModels, which automatically integrates with the Android lifecycle. Here, &lt;code&gt;MyViewModel&lt;/code&gt; depends on &lt;code&gt;UserRepository&lt;/code&gt;, which is injected by Koin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without annotations, the dependencies and their relationships are explicit in the code, making it easier to understand and maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;strong&gt;Kotlin Multiplatform Support&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kotlin Multiplatform (KMP) has become increasingly popular for developing cross-platform applications. Koin supports &lt;a href="https://insert-koin.io/docs/reference/koin-mp/kmp" rel="noopener noreferrer"&gt;multiplatform development&lt;/a&gt;, allowing developers to define dependencies that work across Android, iOS, and other platforms seamlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of Multiplatform Module:
&lt;/h3&gt;

&lt;p&gt;Here’s how you might set up a common module for a multiplatform project with Koin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Defining a common module for multiplatform&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;commonModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;NetworkClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Singleton for network client&lt;/span&gt;
    &lt;span class="nf"&gt;factory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;DataRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Factory for repository&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Sample KMP service with shared dependency&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NetworkClient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;requestData&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Response from NetworkClient"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DataRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;networkClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NetworkClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;networkClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;p&gt;In this setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;NetworkClient&lt;/code&gt; dependency is shared across platforms.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DataRepository&lt;/code&gt; relies on &lt;code&gt;NetworkClient&lt;/code&gt;, promoting code reuse and reducing boilerplate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Koin’s multiplatform modules allow consistent DI practices across platforms, making it easier to maintain and scale cross-platform applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;strong&gt;Enhanced Performance and Lightweight Nature&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Koin is lightweight and avoids the overhead of compile-time dependency injection, which can slow down build times. Instead, Koin performs DI at runtime, optimizing build speed and making it especially beneficial for CI/CD pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Singletons and Factories to Control Instance Lifetimes:
&lt;/h3&gt;

&lt;p&gt;Koin’s &lt;code&gt;single&lt;/code&gt; and &lt;code&gt;factory&lt;/code&gt; functions give you precise control over the lifecycle of your dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;performanceModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;ExpensiveResource&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Singleton for a resource-heavy dependency&lt;/span&gt;
    &lt;span class="nf"&gt;factory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;LightweightTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Factory for lightweight tasks&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExpensiveResource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Simulate an expensive resource initialization&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LightweightTask&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Execute task&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By controlling dependency lifetimes with &lt;code&gt;single&lt;/code&gt; and &lt;code&gt;factory&lt;/code&gt;, you can optimize performance by limiting the instantiation of resource-heavy objects while keeping lightweight tasks efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;strong&gt;Scalable Modularization&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In modern applications, modularization enables teams to work on different features independently, improving scalability and flexibility. Koin’s &lt;a href="https://insert-koin.io/docs/reference/koin-core/modules" rel="noopener noreferrer"&gt;module system&lt;/a&gt; supports this approach by allowing dependencies to be organized into distinct modules that can be loaded or unloaded as needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Organizing Dependencies by Feature:
&lt;/h3&gt;

&lt;p&gt;Here’s an example of separating dependencies into modules by feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// User feature module&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;userModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;factory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;UserViewModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Product feature module&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;productModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;factory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;ProductViewModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Each feature module contains its own dependencies, encapsulating logic and promoting modularity.&lt;/li&gt;
&lt;li&gt;Developers can load only the necessary modules for specific features, keeping the dependency structure clean and manageable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach supports modern architecture patterns like &lt;strong&gt;MVVM&lt;/strong&gt; and &lt;strong&gt;Clean Architecture&lt;/strong&gt;, making it easier to scale applications as features and dependencies grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;strong&gt;Community and Ecosystem Growth&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Since its release, Koin has fostered a vibrant community that continuously enhances the framework. In 2025, Koin has evolved to support the latest trends in Kotlin and Android development, with frequent updates, plugins, and extensions. The support from its community ensures that Koin remains a future-proof DI framework with reliable and robust features.&lt;/p&gt;

&lt;p&gt;As Kotlin Multiplatform becomes more widely adopted, Koin’s community provides resources and plugins that facilitate smooth multiplatform development, further enhancing its value as a versatile and reliable framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. &lt;strong&gt;Seamless Testing Capabilities&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Testing DI setups can be challenging, but Koin simplifies it with built-in testing modules that allow developers to mock dependencies easily. This feature is particularly useful in test-driven development (TDD) and continuous integration (CI) environments, where testing dependency injection setups is crucial.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Test Dependencies:
&lt;/h3&gt;

&lt;p&gt;Here’s an example of &lt;a href="https://insert-koin.io/docs/reference/koin-test/testing/" rel="noopener noreferrer"&gt;setting up test dependencies with Koin&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyViewModelTest&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;KoinTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mockRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockk&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@Before&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;startKoin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mockRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Mocked UserRepository for testing&lt;/span&gt;
                &lt;span class="nf"&gt;viewModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;MyViewModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;testViewModelFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Testing MyViewModel logic with mock dependencies&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;KoinTest&lt;/strong&gt;: An interface that integrates Koin into testing environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mocked Dependencies&lt;/strong&gt;: The real dependencies are replaced with mocks, allowing isolated and controlled testing of components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Koin, developers can easily inject mocks and override dependencies, making it simple to maintain robust test coverage and ensure code quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. &lt;strong&gt;Flexibility for Any Type of Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Koin’s flexibility extends beyond Android and mobile applications. As Kotlin’s use expands into backend and web development, Koin has proven to be an adaptable DI solution for a variety of project types. It integrates well with frameworks like &lt;strong&gt;Ktor&lt;/strong&gt; for building backend services, providing efficient dependency management across all application layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of Koin in a Ktor Project:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;install&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Koin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;koinModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;routing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DataRepository&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;koinModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;DataRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DataRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Data from repository"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Koin’s DI capabilities extend to server-side development, where it integrates smoothly with Ktor, enhancing modularity and maintainability.&lt;/li&gt;
&lt;li&gt;The Ktor server can inject dependencies defined in Koin modules, ensuring consistency across all project layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Koin’s Kotlin-first design, ease of use, multiplatform support, and lightweight runtime architecture make it a compelling choice for dependency injection in 2025. As Kotlin continues to expand across platforms, Koin’s intuitive and annotation-free approach ensures clear, concise, and maintainable DI setups for modern applications. For Kotlin developers building cross-platform, modular, and testable applications, Koin provides an efficient and future-proof solution for managing dependencies with ease.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>koin</category>
      <category>multiplatform</category>
    </item>
    <item>
      <title>Memory Management and Garbage Collection in Kotlin Multiplatform XCFramework</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Sun, 27 Oct 2024 19:54:02 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/memory-management-and-garbage-collection-in-kotlin-multiplatform-xcframework-15pa</link>
      <guid>https://dev.to/arsenikavalchuk/memory-management-and-garbage-collection-in-kotlin-multiplatform-xcframework-15pa</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the previous article, we explored &lt;a href="https://dev.to/arsenikavalchuk/manual-memory-management-and-garbage-collection-in-kotlin-multiplatform-native-shared-libraries-1ll3"&gt;manual memory management and garbage collection in Kotlin Multiplatform (KMP) with a focus on shared libraries&lt;/a&gt;. KMP's ability to generate shared libraries for C++ projects and frameworks for Apple platforms makes it highly versatile, but each output format brings unique challenges and advantages in memory management. This article dives into using an Apple XCFramework from Kotlin Multiplatform, focusing on memory management and garbage collection (GC) in a Swift-based environment. We’ll highlight key differences from the shared library implementation and observe how automatic memory management in Swift’s ARC simplifies the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building and Using an XCFramework in Swift
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Building an XCFramework
&lt;/h3&gt;

&lt;p&gt;Creating an XCFramework with Kotlin Multiplatform is straightforward, especially with Gradle's built-in support for Apple frameworks. The process is defined in the build script, as seen in the &lt;a href="https://github.com/arskov/kmp-native-pg/blob/main/lib/build.gradle.kts" rel="noopener noreferrer"&gt;Gradle configuration example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Key steps for building the XCFramework include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setting Up Target Platforms&lt;/strong&gt;: In the &lt;code&gt;kotlin&lt;/code&gt; block of &lt;code&gt;build.gradle.kts&lt;/code&gt;, specify the Apple targets (&lt;code&gt;iosArm64&lt;/code&gt;, &lt;code&gt;iosX64&lt;/code&gt;, and &lt;code&gt;iosSimulatorArm64&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defining XCFramework Output&lt;/strong&gt;: Use the &lt;code&gt;framework&lt;/code&gt; directive to configure the XCFramework output, specifying necessary build parameters like &lt;code&gt;baseName&lt;/code&gt; and the output directory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building with Gradle&lt;/strong&gt;: Use the command &lt;code&gt;./gradlew assembleKmpSampleXCFramework&lt;/code&gt; to generate the framework, which can then be imported into an Xcode project. The task name will depend on the &lt;code&gt;XCFramework(name)&lt;/code&gt; passed in the &lt;code&gt;build.gradle.kts&lt;/code&gt;. In our case it is &lt;code&gt;KmpSample&lt;/code&gt; and the task name is &lt;code&gt;assembleKmpSampleXCFramework&lt;/code&gt; respectively.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Using the XCFramework in a Swift Project
&lt;/h3&gt;

&lt;p&gt;The XCFramework can be added directly to an Xcode project, allowing seamless use of Kotlin code in Swift. The &lt;a href="https://github.com/arskov/kmp-swift" rel="noopener noreferrer"&gt;Swift sample project&lt;/a&gt; demonstrates this. &lt;/p&gt;

&lt;p&gt;I won't spend much in this article on how do you exactly include the framework into the Swift project. But essentially it just requires creating a Swift project (like a CLI app, programming language: Swift), and drag-n-dropping the &lt;code&gt;KmpSample.xcframework&lt;/code&gt; folder from &lt;code&gt;build/XCFrameworks/[debug,release]/&lt;/code&gt; directly into Xcode project.&lt;/p&gt;

&lt;p&gt;Now let's focus on the example of invoking Kotlin methods from Swift:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;
&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;KmpSample&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;clazzInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Call interfaceMethod&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;resultString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;interfaceMethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Result from interfaceMethod: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;resultString&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Call returnInt&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;intResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;returnInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Result from returnInt: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;intResult&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Call returnLong&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;longResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;returnLong&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Result from returnLong: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;longResult&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Passing a byte array to a Kotlin function&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;byteArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UInt8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0xCA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xFE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xCA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xFE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xCA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xFE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xCA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xFE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;byteArray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="n"&gt;byteArray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withUnsafeMutableBytes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;rawBufferPointer&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="kt"&gt;KmpSampleKt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readNativeByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;byteArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rawBufferPointer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baseAddress&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In contrast to the shared library setup, using the XCFramework in Swift reduces the need for manual disposal of resources. Swift's ARC automatically manages object references, freeing developers from the memory management steps required in C++.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Management in Kotlin Multiplatform with XCFramework
&lt;/h2&gt;

&lt;p&gt;Kotlin Native provides a garbage collector (GC) that manages memory for objects created within the Kotlin framework. Although Swift’s ARC handles the lifespan of objects, the GC in Kotlin remains active, especially for objects created internally within Kotlin’s runtime. To monitor GC behavior, pass the &lt;code&gt;-Xruntime-logs=gc=info&lt;/code&gt; flag during compilation, as configured in the Gradle build &lt;a href="https://github.com/arskov/kmp-native-pg/blob/main/lib/build.gradle.kts#L22" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With GC logging enabled, you’ll see output like this when running the framework in a Swift environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO][gc][tid#1494899][0.000s] Adaptive GC scheduler initialized
[INFO][gc][tid#1494899][0.001s] Set up parallel mark with maxParallelism = 8 and cooperative mutators
[INFO][gc][tid#1494899][0.001s] Parallel Mark &amp;amp; Concurrent Sweep GC initialized
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observing GC Behaviour
&lt;/h3&gt;

&lt;p&gt;To test how Kotlin GC performs under heavy load, we can simulate high-frequency object creation and disposal in Swift. The &lt;a href="https://github.com/arskov/kmp-swift/blob/main/IntegrationGcTest/main.swift" rel="noopener noreferrer"&gt;sample code in IntegrationGcTest&lt;/a&gt; creates millions of &lt;code&gt;KmpClazz&lt;/code&gt; instances, calling methods and disposing of objects in a loop. The following code demonstrates this scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;
&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;KmpSample&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="mi"&gt;10_000_000&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;clazzInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// Call interfaceMethod&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;resultString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;interfaceMethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// Call returnInt&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;intResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;returnInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;// Call returnLong&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;longResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;returnLong&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Created &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; objects"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GC Log Analysis for XCFramework in Swift
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/arskov/21b9c60690aa4b7815115848c6c3123c" rel="noopener noreferrer"&gt;The full GC log for the example above&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The resulting GC log from this loop is extensive. Here’s a segment of the log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO][gc][tid#1796721][16.128s] Epoch #157: Started. Time since last GC 95913 microseconds.
[INFO][gc][tid#1796721][16.138s] Epoch #157: Root set: 0 thread local references, 0 stack references, 0 global references, 1 stable references. In total 1 roots.
[INFO][gc][tid#1796721][16.138s] Epoch #157: Mark: 2728 objects.
[INFO][gc][tid#1796721][16.138s] Epoch #157: Sweep extra objects: swept 58915 objects, kept 68256 objects
[INFO][gc][tid#1796721][16.138s] Epoch #157: Sweep: swept 65528 objects, kept 2728 objects
[INFO][gc][tid#1796721][16.138s] Epoch #157: Heap memory usage: before 6160384 bytes, after 6422528 bytes
[INFO][gc][tid#1796721][16.138s] Epoch #157: Time to pause #1: 32 microseconds.
[INFO][gc][tid#1796721][16.138s] Epoch #157: Mutators pause time #1: 2884 microseconds.
[INFO][gc][tid#1796721][16.138s] Epoch #157: Time to pause #2: 2 microseconds.
[INFO][gc][tid#1796721][16.138s] Epoch #157: Mutators pause time #2: 10 microseconds.
[INFO][gc][tid#1796721][16.138s] Epoch #157: Finished. Total GC epoch time is 10008 microseconds.
[INFO][gc][tid#1796725][16.145s] Epoch #157: Finalization is done in 6885 microseconds after epoch end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Key Observations from the GC Logs
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GC Epoch Frequency&lt;/strong&gt;: The XCFramework GC runs frequent epochs due to high object turnover. Compared to shared libraries, there are significantly more GC epochs (157 vs 31), suggesting a more responsive GC handling objects in short-lived scopes. See &lt;a href="https://gist.github.com/arskov/96ae91a3bc044b17a7d7a6e2447ccca1" rel="noopener noreferrer"&gt;GC log for the shared library&lt;/a&gt; for comparison.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable References and Roots&lt;/strong&gt;: Since objects in Swift go out of scope naturally, stable references are kept to a minimum, which prevents the Kotlin GC from holding on to unreferenced objects, enhancing efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Impact&lt;/strong&gt;: Frequent GC epochs show that although ARC handles disposals, Kotlin’s GC is still active and essential in memory management for stable references within the framework.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Using Kotlin Multiplatform’s XCFramework simplifies memory management in Apple projects by offloading much of the work to Swift’s ARC. This setup reduces the need for explicit disposal, enhancing code readability and reducing potential memory leaks. However, Kotlin Native’s garbage collector still plays an active role, particularly for stable references within the Kotlin framework.&lt;/p&gt;

&lt;p&gt;In the next article, we’ll further investigate performance optimization for KMP GC handling in large-scale Swift applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://kotlinlang.org/docs/multiplatform-build-native-binaries.html" rel="noopener noreferrer"&gt;Configure and build KMP native binaries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kotlinlang.org/docs/native-arc-integration.html" rel="noopener noreferrer"&gt;Integration with Swift/Objective-C ARC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/arskov/kmp-native-pg" rel="noopener noreferrer"&gt;Playground for Kotlin Multiplatform (Native) code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/arskov/kmp-swift" rel="noopener noreferrer"&gt;Using Kotlin Multiplatform XCFramework/Framework in Swift&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>kotlin</category>
      <category>multiplatform</category>
      <category>swift</category>
    </item>
    <item>
      <title>Manual Memory Management and Garbage Collection in Kotlin Multiplatform Native Shared Libraries</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Sun, 27 Oct 2024 16:57:10 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/manual-memory-management-and-garbage-collection-in-kotlin-multiplatform-native-shared-libraries-1ll3</link>
      <guid>https://dev.to/arsenikavalchuk/manual-memory-management-and-garbage-collection-in-kotlin-multiplatform-native-shared-libraries-1ll3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Kotlin Multiplatform (KMP) has opened up exciting opportunities for developers to create cross-platform applications using a shared codebase that can run natively on different platforms, including Android, iOS, macOS, Windows, and Linux. One of the core benefits of KMP is its ability to target native environments through shared libraries and frameworks, particularly useful in projects where both C++ and Apple (iOS/macOS) components need to interact with shared logic without redundant implementations.&lt;/p&gt;

&lt;p&gt;In this article, we’ll focus on building a shared library and an Apple framework from a Kotlin Multiplatform project. Specifically, we’ll explore the differences between a shared library and a framework, with sample GitHub projects illustrating how APIs are structured and generated in each case. This will be followed by a practical guide on using the shared library in a C++ project and an in-depth look at memory management in Kotlin Native, focusing on how garbage collection (GC) functions within KMP. By the end, you’ll have a solid grasp of implementing and managing a shared library and framework in Kotlin Multiplatform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared Library vs. Apple Framework: What’s the Difference?
&lt;/h3&gt;

&lt;p&gt;We will use &lt;a href="https://github.com/arskov/kmp-native-pg/blob/main/lib/src/commonMain/kotlin/design/KmpSample.kt" rel="noopener noreferrer"&gt;the sample KMP project&lt;/a&gt; as an example of the native shared library.&lt;/p&gt;

&lt;p&gt;The sample class that we are using in this article is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;KmpInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;interfaceMethod&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;KmpInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;returnLong&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42L&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;returnInt&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;interfaceMethod&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"KmpClazz"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When working with Kotlin Multiplatform, two primary methods exist for sharing code with native platforms: shared libraries and Apple frameworks. Each serves distinct purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shared Libraries&lt;/strong&gt;: Typically generated as static or dynamic libraries (.so, .dll, or .dylib files), these are more common in environments where the target is a native codebase in C++ or similar languages. The &lt;a href="https://gist.github.com/arskov/961a3bbe2d2d764af480ffec6379dce8#file-libkmpsample_api-h" rel="noopener noreferrer"&gt;generated shared library API&lt;/a&gt; reveals how the Kotlin code translates into C-compatible functions and structures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Apple Frameworks&lt;/strong&gt;: Produced as .framework bundles, these are exclusive to Apple platforms and cater to Swift and Objective-C interoperability. The &lt;a href="https://gist.github.com/arskov/961a3bbe2d2d764af480ffec6379dce8#file-kmpsample-h" rel="noopener noreferrer"&gt;framework API&lt;/a&gt; example shows the Objective-C bridge generated for the Kotlin code, allowing seamless integration with Apple projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The configuration difference for MacOS target can be specified with the following code in &lt;a href="https://github.com/arskov/kmp-native-pg/blob/main/lib/build.gradle.kts#L29-30" rel="noopener noreferrer"&gt;build.gradle.kts&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;macosX64&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;binaries&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;sharedLib&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libraryName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;framework&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libraryName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In terms of structure, the shared library is more barebones, focusing on function exports and C-compatible structures. On the other hand, the Apple framework offers a more robust integration, allowing Swift or Objective-C to call Kotlin code more naturally with less manual intervention.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building and Using a Shared Library in C++ Projects
&lt;/h2&gt;

&lt;p&gt;To use the KMP shared library in a C++ project, some foundational steps include initialization, object creation, and handling pointers and disposal to ensure memory efficiency. Here’s a practical guide to using a KMP shared library in C++ based on the &lt;a href="https://github.com/arskov/kmp-cpp/blob/main/IntegrationMisc/main.cpp" rel="noopener noreferrer"&gt;KMP C++ integration sample code&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps for Using the Shared Library
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt;: Begin by initializing the library symbols to access the APIs exported from Kotlin:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;   &lt;span class="n"&gt;libKmpSample_ExportedSymbols&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;libKmpSample_symbols&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Object Creation&lt;/strong&gt;: Instantiate objects and classes from the Kotlin library by calling the relevant constructors.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;   &lt;span class="n"&gt;libKmpSample_kref_design_KmpClazz&lt;/span&gt; &lt;span class="n"&gt;clazzInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;design&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Invoking Methods&lt;/strong&gt;: Use the &lt;code&gt;lib&lt;/code&gt; object to call Kotlin methods and retrieve results.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;   &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;interfaceMethodResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;design&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interfaceMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"interfaceMethod result: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;interfaceMethodResult&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;DisposeString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interfaceMethodResult&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Dispose of the returned string when no longer needed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Memory Management&lt;/strong&gt;: Carefully dispose of any objects or pointers obtained from the Kotlin side to avoid memory leaks. This includes invoking &lt;code&gt;DisposeStablePointer&lt;/code&gt; for instances not automatically collected by Kotlin Native's garbage collector.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These essential steps provide a structure for incorporating KMP shared libraries in C++ applications, especially when navigating Kotlin’s garbage collection and memory management system in a native environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory Management in Kotlin Multiplatform Native
&lt;/h2&gt;

&lt;p&gt;Memory management in Kotlin Multiplatform involves balancing explicit disposals in C++ with Kotlin Native’s garbage collection (GC) features. Although Kotlin provides automatic memory management, developers need to handle memory references explicitly when using KMP in C++ or native code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kotlin Native Garbage Collection
&lt;/h3&gt;

&lt;p&gt;Kotlin Native incorporates a &lt;a href="https://kotlinlang.org/docs/native-memory-manager.html#garbage-collector" rel="noopener noreferrer"&gt;garbage collector&lt;/a&gt;, which is especially crucial in cross-language contexts where unmanaged code (like C++) interacts with managed code (Kotlin). Enabling detailed GC logging helps understand GC behavior, allowing developers to optimize memory handling. To enable GC logs, pass the &lt;code&gt;-Xruntime-logs=gc=info&lt;/code&gt; flag in the build configuration, as shown in the &lt;a href="https://github.com/arskov/kmp-native-pg/blob/main/lib/build.gradle.kts#L22" rel="noopener noreferrer"&gt;sample Gradle build configuration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s an example GC log output when using this flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO][gc][tid#1494899][0.000s] Adaptive GC scheduler initialized
[INFO][gc][tid#1494899][0.001s] Set up parallel mark with maxParallelism = 8 and cooperative mutators
[INFO][gc][tid#1494899][0.001s] Parallel Mark &amp;amp; Concurrent Sweep GC initialized
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Managing Objects and References
&lt;/h3&gt;

&lt;p&gt;Using GC doesn’t mean we can ignore memory management entirely in C++. Explicit disposal remains necessary for stable references and objects returned from Kotlin to the native environment. Here’s an example showing how to manage references:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;libKmpSample_ExportedSymbols&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;libKmpSample_symbols&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;libKmpSample_kref_design_KmpClazz&lt;/span&gt; &lt;span class="n"&gt;clazzInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;design&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Call and convert the result from returnInt&lt;/span&gt;
&lt;span class="n"&gt;libKmpSample_kref_kotlin_Int&lt;/span&gt; &lt;span class="n"&gt;intResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;design&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KmpClazz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returnInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;nativeInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getNonNullValueOfInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intResult&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"returnInt result: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nativeInt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Dispose of stable pointers&lt;/span&gt;
&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;DisposeStablePointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pinned&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;DisposeStablePointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clazzInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pinned&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;DisposeStablePointer&lt;/code&gt; function cleans up memory allocated by the Kotlin library to prevent memory leaks. The following sample script &lt;a href="https://github.com/arskov/kmp-cpp/blob/main/IntegrationGcTest/main.cpp" rel="noopener noreferrer"&gt;IntegrationGcTest&lt;/a&gt; creates 10 millions of KmpClazz instances in a loop to observe GC activity.&lt;/p&gt;

&lt;h4&gt;
  
  
  Observing GC Behavior with and Without Proper Disposal
&lt;/h4&gt;

&lt;p&gt;With proper disposal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Created 9900000 objects
[INFO][gc][tid#1544690][9.475s] Epoch #31: Started. Time since last GC 230405 microseconds.
[WARNING][gc,gcScheduler][tid#1544103][9.526s] Pausing the mutators until epoch 31 is done
[INFO][gc][tid#1544690][9.534s] Epoch #31: Root set: 0 thread local references, 0 stack references, 0 global references, 2 stable references. In total 2 roots.
[INFO][gc][tid#1544690][9.534s] Epoch #31: Mark: 32730 objects.
[INFO][gc][tid#1544690][9.534s] Epoch #31: Sweep extra objects: swept 0 objects, kept 0 objects
[INFO][gc][tid#1544690][9.534s] Epoch #31: Sweep: swept 311293 objects, kept 32730 objects
[INFO][gc][tid#1544690][9.534s] Epoch #31: Heap memory usage: before 5767168 bytes, after 5767168 bytes
[INFO][gc][tid#1544690][9.534s] Epoch #31: Time to pause #1: 36 microseconds.
[INFO][gc][tid#1544690][9.534s] Epoch #31: Mutators pause time #1: 18493 microseconds.
[INFO][gc][tid#1544690][9.534s] Epoch #31: Time to pause #2: 0 microseconds.
[INFO][gc][tid#1544690][9.534s] Epoch #31: Mutators pause time #2: 8 microseconds.
[INFO][gc][tid#1544690][9.534s] Epoch #31: Finished. Total GC epoch time is 58878 microseconds.
[INFO][gc][tid#1544690][9.534s] Epoch #31: Finalization is done in 77 microseconds after epoch end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Root set: 0 thread local references, 0 stack references, 0 global references, 2 stable references. Total GC epoch time is 58878 microseconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/arskov/96ae91a3bc044b17a7d7a6e2447ccca1" rel="noopener noreferrer"&gt;The full GC log&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without disposal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Created 9900000 objects
[INFO][gc][tid#1495514][25.624s] Epoch #31: Started. Time since last GC 275504 microseconds.
[WARNING][gc,gcScheduler][tid#1494899][26.363s] Pausing the mutators until epoch 31 is done
[INFO][gc][tid#1495514][26.761s] Epoch #31: Root set: 0 thread local references, 1 stack references, 0 global references, 19894275 stable references. In total 19894276 roots.
[INFO][gc][tid#1495514][26.761s] Epoch #31: Mark: 32666 objects.
[INFO][gc][tid#1495514][26.761s] Epoch #31: Sweep extra objects: swept 0 objects, kept 0 objects
[INFO][gc][tid#1495514][26.761s] Epoch #31: Sweep: swept 311357 objects, kept 32666 objects
[INFO][gc][tid#1495514][26.761s] Epoch #31: Heap memory usage: before 5767168 bytes, after 5767168 bytes
[INFO][gc][tid#1495514][26.761s] Epoch #31: Time to pause #1: 1 microseconds.
[INFO][gc][tid#1495514][26.761s] Epoch #31: Mutators pause time #1: 707412 microseconds.
[INFO][gc][tid#1495514][26.761s] Epoch #31: Time to pause #2: 1 microseconds.
[INFO][gc][tid#1495514][26.761s] Epoch #31: Mutators pause time #2: 8 microseconds.
[INFO][gc][tid#1495514][26.761s] Epoch #31: Finished. Total GC epoch time is 1136902 microseconds.
[INFO][gc][tid#1495514][26.761s] Epoch #31: Finalization is done in 55 microseconds after epoch end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Root set: 0 thread local references, 1 stack references, 0 global references, 19894275 stable references. Total GC epoch time is 1136902 microseconds.&lt;/p&gt;

&lt;p&gt;When objects and references are correctly disposed, GC pauses are minimal, and root references remain low, optimizing application performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Kotlin Multiplatform provides developers with a versatile toolkit for creating shared libraries and frameworks that can be utilized across multiple platforms, with both C++ and Apple frameworks supported seamlessly. By understanding the nuances of shared libraries versus frameworks, developers can choose the best integration approach for their needs, leveraging a common Kotlin codebase.&lt;/p&gt;

&lt;p&gt;While Kotlin’s GC simplifies memory management, cross-platform contexts require careful attention to object disposal to avoid performance issues. Proper management of references, enabled by GC insights, helps streamline memory use and maintain application responsiveness. In the following article, we’ll continue exploring GC behavior, particularly within a Swift-based CLI app that interacts with the KMP-built Apple Framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://kotlinlang.org/docs/native-gradle.html" rel="noopener noreferrer"&gt;Get started with Kotlin/Native using Gradle﻿&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kotlinlang.org/docs/native-dynamic-libraries.html" rel="noopener noreferrer"&gt;Kotlin/Native as a dynamic library – tutorial﻿&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/arskov/kmp-native-pg" rel="noopener noreferrer"&gt;Kotlin Mutliplatform (Native) Sample Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/arskov/kmp-cpp" rel="noopener noreferrer"&gt;Xcode C++ Sample Project uses KMP Shared Library&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>kotlin</category>
      <category>multiplatform</category>
      <category>cpp</category>
    </item>
    <item>
      <title>Kotlin Sequences: Efficient and Lazy Collection Processing</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Sun, 20 Oct 2024 18:16:28 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/kotlin-sequences-efficient-and-lazy-collection-processing-g5k</link>
      <guid>https://dev.to/arsenikavalchuk/kotlin-sequences-efficient-and-lazy-collection-processing-g5k</guid>
      <description>&lt;h2&gt;
  
  
  Kotlin Collections Types
&lt;/h2&gt;

&lt;p&gt;Kotlin, a modern programming language that has grown rapidly in popularity due to its concise syntax and powerful features, provides robust support for collections. Collections are a fundamental part of many programming tasks, as they help store and manipulate groups of objects. In Kotlin, the most commonly used collection interfaces are &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, and &lt;code&gt;Map&lt;/code&gt;. These collection types allow developers to handle data efficiently, depending on the specific use case. Let’s take a brief look at these types. (Please note, that I'm not addressing time complexity of particular operations on different types of collections in this article. This topic requires a separate article.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;List&lt;/code&gt;: An indexed collection that allows duplicate elements. In Kotlin, lists are categorized as &lt;code&gt;MutableList&lt;/code&gt; (modifiable) and &lt;code&gt;List&lt;/code&gt; (read-only). Lists maintain the order of insertion, making them ideal for tasks that require data to be processed in sequence.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Set&lt;/code&gt;: A collection that contains no duplicate elements. It is useful when uniqueness is critical. Similar to lists, there are &lt;code&gt;Set&lt;/code&gt; (read-only) and &lt;code&gt;MutableSet&lt;/code&gt; (modifiable) types. Sets are optimal when checking for membership or avoiding duplicates in the collection is a priority.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Map&lt;/code&gt;: A collection of key-value pairs, where each key is unique. Maps are ideal for associative arrays and dictionary-like structures, where each key is mapped to a corresponding value. Again, &lt;code&gt;Map&lt;/code&gt; has corresponding read-only &lt;code&gt;Map&lt;/code&gt; and read-write &lt;code&gt;MutableMap&lt;/code&gt; counterparts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example of these collections in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;myList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Immutable List&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mySet&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Immutable Set, automatically removes duplicates&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;myMap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"one"&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"two"&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"three"&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Immutable Map&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Collections in Kotlin can be mutable (modifiable) or immutable (read-only). This immutability feature aligns with Kotlin's focus on immutability for safer, more predictable code. However, when transforming and filtering data, collections can sometimes become inefficient, especially when working with large datasets. &lt;/p&gt;

&lt;p&gt;Kotlin provides alternative API as &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/-sequence/#sequence" rel="noopener noreferrer"&gt;&lt;code&gt;Sequence&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt;, which provides powerful solution to this problem by allowing lazy evaluation of collection transformations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Essential Methods for Kotlin Collection Filtering and Transformation
&lt;/h2&gt;

&lt;p&gt;Kotlin embraces functional programming paradigms, which encourage writing clean and concise code. Many Kotlin collection operations are based on higher-order functions—functions that take other functions as parameters or return them. This allows Kotlin developers to perform complex data transformations and filtering operations in more convenient way.&lt;/p&gt;

&lt;p&gt;Kotlin offers several transformation and filtering methods for collections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;map()&lt;/code&gt;: Transforms each element in a collection and returns a new collection with the transformed elements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;filter()&lt;/code&gt;: Returns a collection that only contains elements that satisfy a given predicate.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flatMap()&lt;/code&gt;: Flattens a nested collection after applying a transformation function, returning a single collection of transformed elements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sortedBy()&lt;/code&gt;: Sorts a collection based on a specific property of its elements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;reduce()&lt;/code&gt; and &lt;code&gt;fold()&lt;/code&gt;: Both of these methods combine all the elements in a collection into a single result using an accumulator function. The difference is that &lt;code&gt;fold()&lt;/code&gt; allows you to specify an initial value for the accumulator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are examples of common transformations and filtering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;numbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Transform: map&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;doubled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// [2, 4, 6, 8, 10]&lt;/span&gt;

&lt;span class="c1"&gt;// Filter: filter&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;evenNumbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// [2, 4]&lt;/span&gt;

&lt;span class="c1"&gt;// Flatten: flatMap&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;nestedList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;flattened&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nestedList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// [1, 2, 3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These functions are extremely powerful but have one potential downside: when applied to large datasets, they &lt;strong&gt;eagerly evaluate every transformation, creating intermediate collections&lt;/strong&gt;. This eager evaluation can lead to performance issues due to the &lt;strong&gt;creation of unnecessary temporary objects in memory&lt;/strong&gt;. This is where Kotlin’s &lt;code&gt;Sequences&lt;/code&gt; come into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin Sequences: Efficient, Lazy Collection Processing
&lt;/h2&gt;

&lt;p&gt;While Kotlin’s regular collections process elements &lt;strong&gt;eagerly&lt;/strong&gt;, meaning all operations are immediately executed and intermediate collections are created, &lt;strong&gt;Sequences operate in a lazy manner&lt;/strong&gt;. This means that transformations on sequences are only performed as elements are needed. This can lead to significant performance improvements when working with large datasets or expensive computations, as intermediate results are not calculated unless they are actually required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Differences Between Collections and Sequences
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eager vs Lazy Evaluation&lt;/strong&gt;: Collections evaluate operations eagerly, creating intermediate collections, while sequences process elements lazily, avoiding intermediate collections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Sequences are more memory-efficient and can outperform regular collections when chaining multiple transformations on large datasets, since they minimize the creation of temporary collections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Cases&lt;/strong&gt;: Sequences are ideal for processing large datasets or when applying several transformation steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how sequences work in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;numbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Eager evaluation with collections&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;eagerResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="c1"&gt;// Intermediate collections are created for the result of map and filter&lt;/span&gt;

&lt;span class="c1"&gt;// Lazy evaluation with sequences&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;lazyResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asSequence&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Sequences need to be converted back to a collection for use&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the map and filter operations for the &lt;code&gt;lazyResult&lt;/code&gt; sequence are not executed immediately. Instead, each transformation is applied only when necessary, and the entire sequence is processed in a single pass when we call &lt;code&gt;toList()&lt;/code&gt;. This lazy approach saves both time and memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Using Sequences
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency for Large Datasets&lt;/strong&gt;: Sequences can dramatically improve performance by deferring computations until they are needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Intermediate Collections&lt;/strong&gt;: Unlike lists, sequences don’t generate intermediate collections between transformations, which reduces overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composability&lt;/strong&gt;: Sequences are easy to compose with multiple operations like &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, and &lt;code&gt;flatMap&lt;/code&gt;, making complex data transformations efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example: Efficient Sequence Processing
&lt;/h2&gt;

&lt;p&gt;Here’s an example where sequences can make a noticeable difference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bigList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Regular List processing&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processedList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bigList&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Sequence processing&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processedSequence&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bigList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asSequence&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the list processing generates intermediate collections that store the result of the &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;filter&lt;/code&gt; operations, while the sequence performs all operations lazily, ensuring that only the first 10 elements are processed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary: Critical Differences Between Collections and Sequences
&lt;/h2&gt;

&lt;p&gt;The main difference between Kotlin collections and sequences boils down to their evaluation strategy: eager versus lazy. Regular collections like List and Set eagerly process every transformation, creating intermediate collections, which can negatively affect performance when processing large datasets or performing numerous transformations. In contrast, Sequences process elements lazily, deferring computation until it’s necessary. This leads to more efficient memory usage and faster execution times for complex operations, especially when working with large datasets or streams of data.&lt;/p&gt;

&lt;p&gt;To summarize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;regular collections&lt;/strong&gt; when working with small datasets or when eager evaluation won’t cause performance bottlenecks.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;sequences&lt;/strong&gt; when working with large datasets or complex chains of transformations to avoid unnecessary intermediate collections and improve performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kotlin sequences provide a powerful mechanism for lazy, efficient data processing, helping developers write cleaner, more performant code.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>performance</category>
    </item>
    <item>
      <title>Match a String with Regular Expression in Bash</title>
      <dc:creator>Arseni Kavalchuk</dc:creator>
      <pubDate>Sun, 20 Oct 2024 13:51:14 +0000</pubDate>
      <link>https://dev.to/arsenikavalchuk/match-a-string-with-regular-expression-in-bash-3125</link>
      <guid>https://dev.to/arsenikavalchuk/match-a-string-with-regular-expression-in-bash-3125</guid>
      <description>&lt;p&gt;In Bash, matching strings against regular expressions (regex) is a common task for parsing and validating data. Bash offers multiple ways to perform regex matching, including using the &lt;code&gt;grep&lt;/code&gt; command, and more importantly, the &lt;code&gt;=~&lt;/code&gt; test expression for conditional checks directly in Bash scripts. In this article, we'll explore different approaches to matching strings with regex in Bash, with a focus on the &lt;code&gt;=~&lt;/code&gt; operator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ways to Check a String Against a Regex in Bash
&lt;/h2&gt;

&lt;p&gt;Bash provides several tools to check strings against regex patterns. Here are the most common methods:&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the grep Command
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;grep&lt;/code&gt; command is a powerful tool to search for patterns in files or standard input. It supports regex matching by default and is widely used for string searching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"teststring"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"test.*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using =~ Test Expression
&lt;/h3&gt;

&lt;p&gt;Bash built-in conditional expressions allow regex matching using the &lt;code&gt;=~&lt;/code&gt; operator within the test &lt;code&gt;[[ ]]&lt;/code&gt;. This approach is efficient for matching strings in scripts without relying on external commands like grep.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"teststring"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^test &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Matches!"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No match!"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using awk
&lt;/h3&gt;

&lt;p&gt;Another way to match regex in bash is with the &lt;code&gt;awk&lt;/code&gt; command, which has built-in regex support.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"teststring"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/test/'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this article, we will focus on the &lt;code&gt;=~&lt;/code&gt; operator as it is an efficient and versatile tool for regex matching in Bash scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Regular Expressions?
&lt;/h2&gt;

&lt;p&gt;Regular Expressions (regex) are sequences of characters that form search patterns, typically used for pattern matching in strings. They allow users to match complex patterns in text, making them a powerful tool for data parsing, validation, and text processing. Regex is used in many programming languages and tools like Perl, Python, JavaScript, grep, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Symbols and Patterns
&lt;/h3&gt;

&lt;p&gt;Regular expressions consist of literals and special characters (metacharacters) that define the search pattern. Some of the most commonly used regex symbols include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dot &lt;code&gt;.&lt;/code&gt;: Matches any single character except a newline.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;a.b&lt;/code&gt; matches acb, a1b, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Caret &lt;code&gt;^&lt;/code&gt;: Anchors the match at the start of a string.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;^test&lt;/code&gt; matches strings starting with test.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Dollar &lt;code&gt;$&lt;/code&gt;: Anchors the match at the end of a string.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;test$&lt;/code&gt; matches strings ending with test.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Asterisk &lt;code&gt;*&lt;/code&gt;: Matches zero or more occurrences of the preceding character or group.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;ab*c&lt;/code&gt; matches &lt;code&gt;ac&lt;/code&gt;, &lt;code&gt;abc&lt;/code&gt;, &lt;code&gt;abbc&lt;/code&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Plus &lt;code&gt;+&lt;/code&gt;: Matches one or more occurrences of the preceding character or group.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;ab+c&lt;/code&gt; matches &lt;code&gt;abc&lt;/code&gt;, &lt;code&gt;abbc&lt;/code&gt;, but &lt;code&gt;not ac&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Square Brackets ([]): Matches any one of the enclosed characters.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;[abc]&lt;/code&gt; matches &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, or &lt;code&gt;c&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Escape Sequence &lt;code&gt;\&lt;/code&gt;: Escapes special characters, allowing them to be treated as literals.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;\.com&lt;/code&gt; matches &lt;code&gt;.com&lt;/code&gt; instead of treating &lt;code&gt;.&lt;/code&gt; as a wildcard.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Parentheses &lt;code&gt;()&lt;/code&gt;: Groups multiple characters or expressions.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;(ab)+&lt;/code&gt; matches &lt;code&gt;ab&lt;/code&gt;, &lt;code&gt;abab&lt;/code&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Pipe &lt;code&gt;|&lt;/code&gt;: Acts as a logical OR operator to match different alternatives.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;a|b&lt;/code&gt; matches &lt;code&gt;a&lt;/code&gt; or &lt;code&gt;b&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Regex Pattern Examples
&lt;/h3&gt;

&lt;p&gt;Here are a few examples of common regex patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Email validation: &lt;code&gt;^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$&lt;/code&gt;. This pattern matches simple email addresses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Phone number: &lt;code&gt;^\(\d{3}\) \d{3}-\d{4}$&lt;/code&gt;. Matches phone numbers in the format &lt;code&gt;(123) 456-7890&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URLs: &lt;code&gt;^https?:\/\/[^\s/$.?#].[^\s]*$&lt;/code&gt;. Matches URLs starting with &lt;code&gt;http&lt;/code&gt; or &lt;code&gt;https&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regular expressions are invaluable in scripting for tasks like validation, substitution, and parsing of structured text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using =~ Test Expression in Bash
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;=~&lt;/code&gt; operator allows you to perform regex matching directly within Bash scripts, which is especially useful for writing conditional logic based on patterns. Let's explore its usage with an example of matching a host name that follows a canonical domain pattern, such as &lt;code&gt;cdn.mydomain.com&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1: Basic Domain Name Matching
&lt;/h3&gt;

&lt;p&gt;Here is a simple Bash script that uses &lt;code&gt;=~&lt;/code&gt; to check if a string matches a domain pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cdn.mydomain.com"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^cdn&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;a-zA-Z0-9]+&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;a-z]&lt;span class="o"&gt;{&lt;/span&gt;2,&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Valid CDN domain"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Invalid domain"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;^cdn\.&lt;/code&gt; ensures the hostname starts with &lt;code&gt;cdn.&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[a-zA-Z0-9]+&lt;/code&gt; matches the domain name portion (letters and numbers).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\.[a-z]{2,}$&lt;/code&gt; matches the top-level domain (like &lt;code&gt;.com&lt;/code&gt;, &lt;code&gt;.net&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example 2: Matching Subdomains
&lt;/h3&gt;

&lt;p&gt;You can also expand this logic to handle more complex subdomain patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"static.cdn.mydomain.com"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^[a-z]+&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;cdn&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;a-zA-Z0-9]+&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;a-z]&lt;span class="o"&gt;{&lt;/span&gt;2,&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Valid subdomain"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Invalid subdomain"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example allows the first part of the hostname to be dynamic, matching subdomains like &lt;code&gt;static.cdn.mydomain.com&lt;/code&gt; or &lt;code&gt;images.cdn.mydomain.com&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 3: Extracting Parts of a Domain
&lt;/h3&gt;

&lt;p&gt;In some cases, you may want to capture parts of the string using regex groups and &lt;code&gt;BASH_REMATCH&lt;/code&gt; to extract relevant information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"images.cdn.mydomain.com"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;([&lt;/span&gt;a-z]+&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;cdn&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;a-zA-Z0-9]+&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;a-z]&lt;span class="o"&gt;{&lt;/span&gt;2,&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Subdomain: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_REMATCH&lt;/span&gt;&lt;span class="p"&gt;[1]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No match"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;${BASH_REMATCH[1]}&lt;/code&gt; will store the first captured group, i.e., the subdomain (images in this case).&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Matching strings with regular expressions in Bash is a common task for processing and validating input. While &lt;code&gt;grep&lt;/code&gt; and other external tools provide regex capabilities, the &lt;code&gt;=~&lt;/code&gt; operator is a native Bash feature for in-line regex matching, making it efficient and easy to use in scripts. By mastering regular expressions and using the &lt;code&gt;=~&lt;/code&gt; test expression, you can handle complex pattern matching, validate data like domain names, and even extract specific parts of strings for further processing in your Bash scripts.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>terminal</category>
      <category>cli</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
