惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
博客园 - Franky
MyScale Blog
MyScale Blog
L
LangChain Blog
Martin Fowler
Martin Fowler
Recent Announcements
Recent Announcements
Stack Overflow Blog
Stack Overflow Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 司徒正美
量子位
A
About on SuperTechFans
C
Check Point Blog
大猫的无限游戏
大猫的无限游戏
Last Week in AI
Last Week in AI
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
I
InfoQ
V
Visual Studio Blog
Vercel News
Vercel News
B
Blog
爱范儿
爱范儿
aimingoo的专栏
aimingoo的专栏
U
Unit 42

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Swift Closures — Accepting Functions as Parameters 🎯
Gamya · 2026-06-26 · via DEV Community

So far we've been passing closures into functions that Swift provides — like sorted(), filter(), and map(). But what if you wanted to write your own function that accepts another function as a parameter? That's exactly what we're covering today. 🍥

This might sound complicated, but once you see it in action it starts to make a lot of sense — and it's everywhere in SwiftUI.


Why Would You Even Want This?

Before we write any code, let's think about why this matters.

Imagine you're building an anime battle app that needs to fetch data from a server — maybe pulling in a list of all One Piece characters. Your iPhone can do billions of things per second, but waiting for a server response can take half a second or more. That's practically glacial by comparison.

If your app just sat there waiting for the server to respond, the whole UI would freeze. Nobody wants that.

The solution? Pass in a closure that says: "go do this slow work, and when you're done, call this function with the result." Your app keeps running smoothly, and the closure fires when the data arrives. That's closures as parameters in a real-world nutshell. 🌀


Writing a Function That Accepts a Function

Let's start with a practical example. Here's a function that generates an array of random jutsu power levels by calling another function repeatedly:

func generatePowerLevels(count: Int, using generator: () -> Int) -> [Int] {
    var levels = [Int]()

    for _ in 0..<count {
        let newLevel = generator()
        levels.append(newLevel)
    }

    return levels
}

Let's break down what's happening on that first line:

func generatePowerLevels(count: Int, using generator: () -> Int) -> [Int]

  • count: Int — how many power levels to generate
  • using generator: () -> Int — a function parameter called generator, which takes no parameters itself but returns an Int every time it's called
  • -> [Int] — the whole generatePowerLevels function returns an array of integers

Inside the function, we just call generator() on each loop iteration, collecting its returned value into our array.

Now let's call it using a trailing closure:

let powerLevels = generatePowerLevels(count: 5) {
    Int.random(in: 1...9000)
}

print(powerLevels) // e.g. [4521, 8832, 312, 7741, 999]

Swift sees the trailing closure and knows it matches the generator: () -> Int parameter — no labels needed.

You can also pass in a named function instead of a closure:

func randomChakra() -> Int {
    Int.random(in: 1...9000)
}

let chakraLevels = generatePowerLevels(count: 5, using: randomChakra)
print(chakraLevels)

Both produce exactly the same result — a closure and a named function are interchangeable here, because they have the same type: () -> Int.


Reading the Function Signature

The trickiest part of accepting functions as parameters is reading the syntax. Let's slow down on it:

func generatePowerLevels(count: Int, using generator: () -> Int) -> [Int]

There are two -> arrows here, which can be confusing at first:

  • The first -> (inside () -> Int) belongs to the parameter function — it describes what the function we're passing in returns
  • The second -> (at the end, -> [Int]) belongs to our function — it describes what generatePowerLevels itself returns

Think of it like this: generator is a function that lives inside the parameter list. It has its own type, just like Int or String would — it just happens to be a function type.


Multiple Trailing Closures

Here's something that appears constantly in SwiftUI: functions that accept multiple function parameters.

Imagine an anime training sequence that needs to run three stages — warmup, training, and cool-down — each customizable:

func runTrainingArc(warmup: () -> Void, training: () -> Void, cooldown: () -> Void) {
    print("🏃 Starting warmup...")
    warmup()
    print("⚔️ Starting training...")
    training()
    print("🧘 Starting cooldown...")
    cooldown()
    print("✅ Training arc complete!")
}

When calling a function with multiple trailing closures, the first one works exactly like before — no label, just {. But the second and third each get their label written outside the brace:

runTrainingArc {
    print("Stretching and light jogging")
} training: {
    print("Naruto Shadow Clone Jutsu x1000")
} cooldown: {
    print("Ramen break 🍜")
}

Output:

🏃 Starting warmup...
Stretching and light jogging
⚔️ Starting training...
Naruto Shadow Clone Jutsu x1000
🧘 Starting cooldown...
Ramen break 🍜
✅ Training arc complete!

This multiple-trailing-closure syntax is something you'll see all the time in SwiftUI — for example, creating a Section with a header, content, and footer each uses a separate trailing closure.


The Function Type Cheat Sheet

When writing function parameters, here's how to read and write the types:

What the function does Its type
Takes nothing, returns nothing () -> Void
Takes nothing, returns an Int () -> Int
Takes a String, returns nothing (String) -> Void
Takes two Strings, returns a Bool (String, String) -> Bool

The parameter list goes in the first (), and the return type goes after ->. That's all function types are — a description of what goes in and what comes out.


Why This Matters for SwiftUI

In SwiftUI, almost every component you build uses this pattern. A Button accepts a function for what happens when tapped, and a function for what to display. A List accepts a function to generate each row. Even a VStack uses a closure to hold all its child views.

Once you're comfortable with the idea of passing functions around as arguments, SwiftUI's syntax stops looking mysterious and starts reading like a natural description of your UI. That's the payoff for all this closure work. 🌸


Wrap Up

Concept What It Means
Function as parameter You can pass a function (or closure) as an argument to another function
() -> Int A function type — takes nothing, returns an Int
Multiple trailing closures Call each extra closure with its label outside the brace
Named function vs closure Interchangeable as long as the type matches

This article was written by me; AI was used to improve grammar and readability.